Art is rough
Why’s Poignant Guide claims that after learning Ruby you will write code so elegant it will make you cry. Paul Graham was not so dramatic, but he was closer to the mark. Lisp teaches you the elegance and grace of recursive and applicative programming. This creates beautiful and concise code.
Unfortunately, there is sometimes quite a bit of overhead associated with it. On the newLisp forums, someone replacing items from one list that matched items from another. He has two lists; list one contains about 30,000 strings. List two is a two dimensional list containing about 100,000 strings total.
The idea is to check for equality against the 30k strings in list one on each of the cells in list two, then replace that with a predefined string if equality is met.
The elegant solution is to use applicative and recursive algorithms. Naturally, the forum user used a recursive function, ref-all, which provides an index of placement of an atom in a list (i.e. (ref-all "baz" '("foo" "bar" "baz" "bat"))
=> 2). Then he mapped a lambda to list one that ref-all’d the item from list one in list two, replacing it with “FOO”.
The problem was that this was using a recursive function on a huge list over and over again, and newLisp is not optimized for large lists of strings as it is. It turns out that I was able to speed it up by using one of newLisp’s iterators, dolist, which simply iterates over a list. The code I ended up with was:
(set 'relacement "FOO") (dolist (o one) (dolist (r (ref-all o two)) (nth-set (two r) replacement)))
This reduced execution time by almost 10% on my machine (granted, my machine is powered by hamsters).
This just goes to show, efficiency is more important than elegance. If the code doesn’t do what it needs to do in an effective manner, what does it matter how pretty it is?