leah blogs

May 2004

08may2004 · Simplifying s-expressions

Many people have their problems with lispy s-expressions because they involve many parentheses. Especially if Lisp is coded in the way it should, “like a waterfall”, that is: functional, reusing values, avoiding sequences. Then code often looks like this (example taken from sb-md5):

(defparameter *t*
  (make-array 64 :element-type 'ub32
          :initial-contents
          (loop for i from 1 to 64
                collect
                (truncate
                 (* 4294967296
                    (abs (sin (float i 0.0d0))))))))

Note the 9(!) closing parens at the end; these become difficult to maintain, especially if code gets changed in the middle of it.

Seth Gordon now describes something very clever in a mail to Paul Graham: he invents the ~-syntax. Code which looked like

    (f (g (h x)))

now gets:

    (f ~ g ~ h x)

Notice the reduction of parentheses. Again the first sample:

(defparameter *t*
  ~ make-array 64 :element-type 'ub32
          :initial-contents
          ~ loop for i from 1 to 64
                 collect
               ~ truncate
                 ~ * 4294967296
                    ~ abs ~ sin ~ float i 0.0d0)

Suddenly, we have much less parentheses, but a more mysterious and—at least to Lisp users—more weird syntax.

Also note that there have been former tries to simplify multiple parentheses, for example the superparentheses of Interlisp. They are written as [ and ]. ] closes all parens upto the first [, or to toplevel.

Or, as we can read in the INTERLISP Manual:

The INTERLISP read program treats square brackets as “superparentheses”: a right square bracket automatically supplies enough right parentheses to match back of the last left square bracket (in the expression being read), or if none has appeared, to match the first left parentheses, […]

Now the code would get:

(defparameter *t*
  (make-array 64 :element-type 'ub32
          :initial-contents
          (loop for i from 1 to 64
                collect
                (truncate
                 (* 4294967296
                    (abs (sin (float i 0.0d0]

This looks even more weird than the ~-syntax because it is visibly unbalanced. This is probably the main reason that the superparentheses didn’t made it into Common Lisp.

I, for myself, however consider the ~-syntax to be an interesting, refreshing idea for lisp and hope Paul Graham will implement them. If not in the core language, they are at least possible using a reader extension. Maybe I code them for myself in Common Lisp. Mhmmm…

Copyright © 2004–2022