I’ve been in Japan for 4 weeks now and my time here is not going to waste… between Japanese classes, I’ve been flirting with ocaml, scala, c (I read the K&R book) and now Smalltalk (with Squeak). My casual language survey is coming to an end, with no more obvious omissions, I would think. (covered before: Haskell, Erlang, Scheme and Common Lisp … and this goes without mentioning the others I touched: Python, Perl, Ruby, C++, Java)
No language is perfect. Performance seems indirectly proportional to expressiveness. This is the intuitive answer … and sadly, the one I found experimentally.
I mentioned before my list of programming exercises I try once I get past the introductions and tutorials. Always working on the same problems really helps understand the idioms of a new language.
I tried to code Tower of Hanoi and “benchmark” the time it takes to execute them for a few languages.
Tower of Hanoi, 20 rings:
* Ruby: ~20 seconds
* C: ~1.2 seconds
* OCaml: ~5 seconds
* Scala: ~16 seconds
* Haskell: >2 minutes … stopped it at that point
As for Smalltalk … this is a whole other story. The main motivation is Seaside, of course. Smalltalk is interesting in itself for many reasons:
- You can see where Ruby got its inspiration
- You can experience what object orientation really means
- You can try “crazy” stuff like switching the garbage collector on the fly …
- You can experience the-language-is-the-environment-is-the-IDE, which seems like both a blessing and a curse
I’m trying to get to the point where I can write a few webapps in Seaside and see if my whole world is transformed. If you want to understand “why Seaside”, you can watch The Heretic Web Framework – Seaside. The idea of continuations and the idea of assigning code blocks to hyperlinks (instead of named goto: URLs) are definitely something worth investigating.
It doesn’t mean that Smalltalk is a destination… it’s just one of the stops along the way.
Why was Haskell taking that long?
Good question :)
I make no claim at expertise in Haskell, and here’s what I had come up with: http://s3.amazonaws.com/mps/hanoi.hs
You can compare that with http://www.kernelthread.com/hanoi/html/hs.html which generates the whole list in memory (lazily, of course) and outputs it. Keep in mind that 20 rings represents 2^20 lines of output.
Haskell is a fun language with a lot of will-hurt-your-brain ideas … I don’t want to make it sound like this is representative of anything.
How was Smalltalk perf?
I’m surprised about Haskell. Looking at http://shootout.alioth.debian.org/ it seems to perform quite well.
Also Lua and Io look very interesting too.
Nice post!
My guess is you didn’t compile the Haskell code, but instead ran it in an interpreter like Hugs or GHCi.
This slight refactor:
import System.Environment
showMove src dst = putStrLn (show src ++ ” -> ” ++ show dst)
data T = One | Two | Three
deriving Show
hanoi :: Int -> T -> T -> T -> [(T, T)]
hanoi 1 src dst acc = [(src, dst)]
hanoi n src dst acc = hanoi (n-1) src acc dst ++
hanoi 1 src dst acc ++
hanoi (n-1) acc dst src
main = do
args <- getArgs
let n = read (head args)
mapM_ (uncurry showMove) (hanoi (n :: Int) One Two Three)
Runs in 10seconds on my box, when compiled:
ghc -O2 A.hs
Note its extrememly naive — you could for a start replace (++) on lists by an O(1) append operation.
wrt Smalltalk:
Tower of Hanoi, as far as I understand its performance, is IO bound. In Smalltalk, I guess I could output to the Transcript which is terribly slow (their own words!). My interest in Smalltalk is purely non-performance related … although it has been claimed faster than Ruby in most cases. We’ll see how that goes.
wrt Haskell.
Thanks! I googled for “haskell performance” last night after I posted this. There are a number of tips and tricks out there. I had not been looking to make this really fast. In fact, I could have adopted a more imperative style to make it faster and forego the list creation completely … but that wouldn’t be very Haskell-ish.