S-expressions readability

lispreadability

In a nutshell and for those who didn't know it, Lisp functions/operators/constructs are all uniformly called like this:

(function arg0 arg1 ... argN)

So what in a C-like language you would express as

if (a > b && foo(param))

is transformed to a Lisp sexp like

(if (and (> a b) (foo param)))

. As things get more real/complicated, so do their corresponding s-expressions, for me.

I'm aware that this is most likely a subjective question, but – is for many Lisp hackers this one little annoyance one will have to always deal with?

Or does one mostly get used to this (lack of) syntax sooner or later?

In any case, is adding breaklines (that you wouldn't add in your C equivalent, most times) for readability a good idea, especially on the long run? Any other suggestions would be welcome.

Best Answer

How do you parse

if (a > b && foo(param)) {
  doSomething();
} else {
  doSomethingElse();
}

The parse tree probably looks something like

if:
  condition:
    and:
      lt:
        left: a
        right: b
      function:
        name: foo
        param: param
  true-block:
    function:
      name: doSomething
  false-block:
    function:
      name: doSomethingElse

hmm... let's serialize this tree into a list, prefix notation

if(and(<(a, b), function(foo, param)), function(doSomething), function(doSomethingElse))

This parse tree format is pretty easy to manipulate, but I have one problem. I hate separators. I like terminators. At the same time, I like sprinkling in whitespace.

if( and (<(a b) function(foo param)) function (doSomething) function ( doSomethingElse))

hmm... the additional whitespace makes certain things harder to parse... Maybe I could just make a rule that the tree is represented as (root leaf leaf leaf).

(if (and (< a b) (function foo param)) (function doSomething) (function doSomethineElse)

Now my serialization of a parse tree is lisp (rename function to apply, and this probably runs). If I want programs that write programs, it's kind of nice to just manipulate parse trees.

This isn't entirely how s-expressions came about, but it was identified early, and it is one feature that lisp programmers use. Our programs are pre-parsed in some sense, and writing programs to manipulate programs is fairly easy because of the format. That's why the lack of syntax is sometimes considered a strength.

But as David said, use an s-expression aware editor. You are more likely to lose track of a closing brace in an s-expression than a closing brace in xml (</foo> only closes <foo>, but right paren closes ANY s-expression). In racket, the use of square brackets for some expressions, coupled with good indenting style, fixes most problems.

The lisp version:

(if (and (< a b) (foo param))
  (doSomething)
  (doSomethingElse))

Not too bad.

Related Topic