13 December 2005

Bitten By the Hygiene Bug

I've noticed that I haven't posted here for a while---been really busy working on the code for the paper on n-body integrators. I'm finally running some real "experiments" (the numerical kind), and am discovering the joy of tight binary orbits in the middle of a star cluster (hint: lots of small steps for the binary = lots of roundoff error over cluster timescales). Hopefully I've got that fixed up now, but you never know until it breaks :).

Anyway, here's a real life example of why hygiene matters. Consider the following code:

(define (vector-n-smallest vector n <)
   (let* ((store (vector-copy vector 0 (+ n 1))))
      (insert-sort! store <)
      (do-range (i (+ n 1) (vector-length vector))
         (vector-set! store n (vector-ref vector i))
         (insert-sort! store <))
      (vector-copy store 0 n)))
Hmm, my custom comparison function keeps complaining it's being fed integers rather than frobs! What's going on?

Turns out that I had defined do-range without macro hygiene, and it's expansion involves the symbol <. It's not rocket science, but it is a good example of why you should care about hygiene. (Note that this problem is "solved" in Common Lisp---I think---because the passed in comparison function lives in the value of the symbol <, while the CL::< numerical comparison lives in the symbol-function of the symbol <, so you have to use a funcall to get the custom comparison while (< ...) does the usual CL thing. Hygiene, on the other hand, just does the right thing.)