Archive for May, 2008

Common Lisp heresy: syntactic lambdas

Saturday, May 3rd, 2008
(defun bracket-reader (stream char)
  (declare (ignore char))
  (let* ((lst (read-delimited-list #] stream t))
         (pos (position '|| lst)))
    (if pos
        `#'(lambda ,(mapcar #'intern (subseq lst 0 pos))
             ,@(nthcdr (1+ pos) lst))
        `#'(lambda (_) ,lst))))

(set-macro-character #[ #'bracket-reader)
(set-macro-character #] (get-macro-character #)))

Closures are beautiful, but the heaviness of CL’s lambda syntax kept jumping out at me as fairly ugly after a few months of writing Smalltalk. The above snippet allows you to write things like:

(mapcar [+ _ 1] '(1 2 3))

and:

(maphash [k v || (print v)] tbl)

Which, to my eyes at least, is nicer than:

(mapcar #'(lambda (x) (+ x 1)) '(1 2 3))

and:

(maphash #'(lambda (k v) (print v)) tbl)

Of course, to add syntax to Lisp is to wade into failure-littered territory. But although no-one agrees how it should be done, I really don’t think it’s a bad idea.