Haskell: It’s like Klingon, but with math
sdtimes.com
sdtimes.com
However, being the first functional language I'm really starting to grok I'm amazed at how powerful and concise it is.
Wasn't it Eric S. Raymond that told us we should all learn at least one functional language (namely lisp) in our lives not necessarily to program in, but to make us a better programmers?
(Problem a slight modification of the one described here: http://blogs.msdn.com/ericlippert/archive/2009/04/15/comma-q... )
The haskell solution:
englishList [] = ""
englishList [only] = only
englishList [first,last] = first ++ " and " ++ last
englishList (first:rest) = first ++ ", " ++ (englishList rest)
It's short, but completely readable. Compare that to the solutions given in the blog comments. englishList: aList
^ aList size > 2
ifFalse: [ aList join: ' and ' ]
ifTrue: [ (aList allButLast join: ',') , ' and ' , aList last ] def englishlist(array)
array[0..-2].join(', ').to_s + (array.size > 1 ? ' and ' : '') + array.last.to_s
end
(Not claiming it's as clear to read, but I miss my old one-liner contests! ;)You can implement it roughly as clearly (although not as efficiently) as such:
def englishlist(array)
case array.length
when 0; ""
when 1; array.first
when 2; array.join(' and ')
else; array.first + ', ' + englishlist(array[1..-1])
end
end
I do love me the Haskell so far, but I'm only into the basics still. Love pattern matching, was one of my favorite aspects of Erlang.This (and others) has a fairly obvious and equally readable counterpart in C++ (or any other imperative language, really), but there's a reason why one doesn't implement it this way in those languages -- and a reason why (some of) the examples given have a certain bias towards iteration.
Wouldn't the same reason hold in haskell? Or do we care about runtime efficiency at all?
This was a little bit of a simplification of things; I don't need to go into great detail to make my point.
The code you are looking at here is NOT tail-recursive. Haskell's implementation of ++, in a strict language, will always push O(n) frames on the stack.
But it IS true that this code is O(1) in stack consumption with Haskell's execution model.
In fact the example above looks tail-recursive to me (at least if you add in an accumulator parameter). That means a good compiler will make it efficient.
It's a lot of fun though, and if even it does nothing but stretch your mind to some new ways of doing things then it's very much worth learning.
The hardest part is in collaboration with people who have been using C for 10+ years and aren't interested in other things. Fortunately we have standards for linking object files together independent of their source language.
Good article too!