1. In which a challenge is thrown, but there is a spanner in the
works!
Haskell suddenly became “important†in the Perl community when Audrey
Tang started to blog about Pugs, the prototype version of the Perl 6
interpreter/compiler. So, when I started looking at Haskell, I did so
with another Perl-monger, larsen, one of the key guys in perl.it. We
worked through some of the exercises in YAHT together when we shared a
flat. Since I moved out we never really got around to doing that, and
I've been working through the exercises in SOE on my own. I realised
that the poor chap was missing out on all the fun! So I thought I could
let him “catch upâ€, but as that would involve having to give up my
precious copy of “Haskell School of Expression†up, even for a few days,
I panicked slightly.
My alternative was almost a stroke of genius. For a couple of months
I've had “Practical Common
Lispâ€, which larsen lent me, on my bookshelf. I even read some of
it! But I've not gone through in any rigorous way. My challenge to him
was to do what I'm doing with SOE and to blog the exercises.
The “concept†is that at the end of it, I will be able to teach him
Haskell, and he can teach me Lisp. If you need to know both to be a
truly great programmer, perhaps we can both at least be half of one of
those!
The flaw, as it happens, would seem to be that PCL doesn't have
seem to have exercises… (though we seem to remember them existing
somewhere, this was only on a brief scan).
2. In which osfameron squees at slime, and criticises the Perl
debugger and REPL
He has already downloaded SLIME, and mentioned how cool the video with Marco
Beringer was. I hadn't seen it so he passed me the link. It is
rather nifty, and certainly you can see how features of Lisp like its
regularity make it a joy to parse and manipulate in an IDE. Other
things, like the incremental compilation are interesting, and the depth
of debugging information is astounding.
Compared to this, perl -debug comes off rather badly.
Actually, compared to a drunken, syphilitic stoat, the Perl debugger
might come off badly, but the SLIME package is really rather well put
together. The Perl REPL has several disadvantages, such as not
understanding lexical scopes and not printing out the results of each
call. The cry of “it's hard to use†is probably just an excuse, after
all, if a tool's worth using, you put time into learning it. The
suspicion though is that the Perl debugger isn't really worth learning.
Certain things add to this conviction: for example, I had a vivid memory
that Larry Wall had declared that he was more of a “print statements
kind of guyâ€. (But, not I can't find it via Google, perhaps I dreamt
it). In any case, there is the fact that generally, Perl programmers,
if they even know about the debugger, tend to use it only for the REPL
(and then moan about it).
At some point, Acme did some work on improving the debugger internals,
documentation and test-suite while creating Devel::ebug,
which looked very cute. In theory at least: I could never get it to
install, and I believe it's now unmaintained and targetting an outdated
version of Catalyst. (Some time passes… some facts are
checked…: eeek! No, there have been 2 releases over the last
couple of months, yay Acme! And my colleague Mattia Barbon submitted
patches, yay Mattia! I guess I'll have to check it out again at some
point).
Anyway, Lisp absolutely has an impressive toolchain. But the aesthetic
appeal (and, yes, I know that this is influenced by a lack of
familiarity) is still lacking – all those #\UPPER-CASE-SYMBOLS,
especially on the stack traces. Meh. Yes, I know this is stupid, but
it is odd that a language whose algorithms and concepts are so beautiful
should look so fugly.
(Of course, I find (well written) perl code pleasant to read, so I may
not be qualified to pronounce on the aesthetics of programming. OTOH,
this Larry Wall quote I do remember (and Google confirms that I
didn't dream it) “Lisp has all the visual appeal of oatmeal with
fingernail clippings mixed inâ€.)
3. In which osfameron ponders the virtues of Perl as a functional
programming language, and sings the praises of join
Since the publication of Dominus's seminal Higher Order Perl,
it's hard to deny that Perl enables some Functional Programming
techniques (though you can certainly argue that some of the techniques
are uglier, harder, or less efficient). The three functions in common
use are map, grep, and join.
When Marco creates the convert-to-morse function, he started by
writing a stream to a string, (nice technique! see also IO::Stringy etc.
in Perl) prints a morse character for every character, followed by a
space. He then points out that there's a spurious space after the last
character.
He then starts musing about how to get rid of this and ends up dealing
with the head of the string first, and then doing the rest of the
string, this time prepending the space. While he starts doing this,
every Perl-programmer's muscle in me is screaming, “use join
you fool!â€
Anyway, he may be doing it this way for pedagogical purposes, but his
solution surprised me nonetheless. And while I was thinking about it, I
noticed that I hadn't come across join in Haskell either yet,
so I decided to write it.
First of all, I thought it would be:
> join j = foldr (\left right -> left ++ j ++ right) []
which compiles like so
*Main> :t join
join :: [a] -> [[a]] -> [a]
But there is a problem
*Main> join "," ["hello","world"]
"hello,world,"
A final comma! Of course as the list is really (“hello†: “world†: [])
the fold will join “worldâ€,â€â€œ. Pesky blighter.
I ended up with the slightly less beautiful:
> join j (v:[]) = v
> join j (v:vs) = v ++ j ++ join j vs
with the same signature. (We could also do join [100] [[1,2], [3,4,5]
for example).
What is the standard Haskellish way of writing join?
(Update: dons on #haskell suggested that the obvious name for this in haskell is "intercalate". Actually intercalate (so named, because "join" is already taken – for joining monads) would work. intercalate would be defined as the concatenation of "intersperse". Steven Ashley suggested this solution too. (Update: and dcoutts in irc backlog, thanks all!)
concat $ intersperse "," ["hello", "world"]
on a related note, while I'm hating crappy REPLs, why does ghci make it so bloody hard to do "import Data.List" (in order to get intersperse)? Interestingly, Perl (5) doesn't have intersperse, as "join" only operates on strings, and it would be nice if it did have the generalised version too.)
4. In which a better REPL for Perl is sighted, and osfameron
bemoans the lyf so short
This morning, via a cpanranting on Rocco Caputo's
Lexical::Persistance, I came across Matt Trout's new-ish Vox blog. As well as an
interesting polemic about Ruby, there's a series
about developing a REPL (called Devel::REPL, not yet on
CPAN but it's on his bast repo, linked from the blog), which uses that
module to allow variables like my $foo to persist from one line
in the REPL to another. Just like they should!
mst also talks a lot about Moose,
the new Perl object framework which is massive news in a subset of the
modern Perl community. It's quoted as bringing to Perl the things that
you would otherwise have to flee to Ruby for. Things like declarative
class generation and function argument unrolling (in an extension iirc).
And (as this post is already too long), “much much moreâ€.
All of which reminds me that, as well as spending time learning Haskell,
I should really keep up to date with learning Perl. Which I
will obviously do in my proverbial Copious Free Time!