What’s with all these parentheses?

I’m fairly certain that every programmer will, at some point in his career, say something along the lines of:

I don’t know, what’s with all these parentheses?

And he will be talking about Lisp. I certainly did a few years ago. It’s quite strange when you’re used to other languages, why would anyone want all these parentheses?

Why have something like this:

(filter (lambda (price)
          (< price 10))

When you can have it like this:

prices.select do |price|
    price < 10

Indeed, there is not much syntactical sugar, as Rubyists say, in most Lisp dialects. If you think about it, there isn’t really much syntax at all: You’re really just writing a syntax tree in Lisp’s list literals. Considering that, the syntax is actually pretty clear. Let’s look at what this might look like written in JavaScript’s array literals:

[filter, [lambda, [price],
           [lt, price, 10]],

Not that much different, eh? That’s what Lisp is. And that’s why Lisp macros are so powerful: You can easily transform these data structures into something else, changing your code. I can’t think of a single other language that lets me do that. Another benefit is that when looking at Lisp code, you normally don’t have to wonder about things like operator precedence and strange literals you didn’t know, the syntax is unambiguous.

So if the parentheses are what’s separating you and Lisp, give it a chance. No one I know who gave Lisp the chance it deserves ever regretted it, whether or not it became their main language.

6 Responses

  1. As far as I know one must distinguish between a parse tree (“concrete” syntax tree) and a syntax tree (abstract syntax tree; AST). In a typical compiler one first derives a parse tree from the input, which usually involves a lot of “intermediate” nodes that are only necessary to provide syntactical correctness.

    While or after this is done the AST is being built, which consists only of the nodes that makes up the source programm (no “intermediates” here). When writing LISP one writes down the AST not the parse tree.

    Either way, nice post – reminds me why I like LISP

  2. Thanks, you’re right, it’s of course a syntax tree. Fixed it.

  3. I can’t think of a single other language that lets me do that.

    Io actually has similar properties, with code being a tree that can be inspected and modified at runtime, and I think it’s worth taking a look at it. Of course, the influence for this language feature is none other than Lisp…

  4. Io has been on my list of languages I want to investigate, that makes it move up 🙂

    Can’t find anything on how to write macros (or what they call it) though, can you point me to something?

  5. I am not an expert on Io, but from what I gathered, you usually don’t want to write macros, because you can take advantage of the fact that arguments to messages are passed as references to the expressions. This makes it possible to write your own control structures as methods, accessing the unevaluated argument expressions using something like call evalArgAt(0).

    For example, the Io documentation shows how to implement your own if. The regular if in Io is really only a method, too.

    Then, Io gives you a lot of power by providing methods like curlyBrackets and squareBrackets, that are called when the respective characters are used, and which you can override. This allows you, for instance, to make JSON valid Io code in a surprisingly simple way.

    I have yet to delve deeper into Io, too, and while it doesn’t look as elegant as Lisp, I like its simplicity.

Leave a Reply