That’s what many people I know think of when they hear my favourite languages are all Lisp derivatives such as Scheme or Clojure. They usually follow that up with a statement indicating that there are just too many brackets in Lisp.

For a while I’ve wondered about this and after a little bit of study I think most people are wrong. They’re fixated on the position of the brackets not on the number. Most languages use a lot of brackets, be they [ … ], ( … ), { … } or < … >. Anyone who codes up XML knows all too well how many of those < … > brackets they’ll be dealing with.

So I looked around for some simple samples of accumulator code fragments and found this on Paul Graham’s site. Sure, Graham is a Lisp geek, but a quick look at the following C++ code quickly shows something:

struct Acc { Acc(T n) : n(n) {} template <typename U> Acc(const Acc<U>& u) : n(u.n) {} template <typename U> T operator()(U i) { return n += 1; } T n; }; template <typename T> Acc<T> foo(T n) { return Acc<T>(n); }

vs. Scheme which is as follows:

(define (foo n) (lambda (i) (set! n (+ n i)) n))

Now, it’s patently obvious that the Scheme source is *much* shorter and, in my opinion, much clearer. It returns a lambda which can be bound to a variable that becomes an accumulator. There’s a certain mathematical beauty to it.

But as for brackets, we see the Scheme example having six pairs of brackets. The C++? Well, it has fourteen!

Hmm. That’s odd. Let’s try another example, something that may not play to Lisp’s power courtesy of the Lambda Calculus. Let’s try factorial. First in Scheme.

(define (factorial n) (if (eq? n 0) 1 (* n (factorial (- n 1)))))

What we see is seven pairs of brackets. But, I still find it readable. Also, under Scheme you can try weird things like (factorial 12345) and actually get a result. Under most other languages, you’ll get an error or zero. But what does that look like in C?

int factorial (int n) { if (n == 0) return 1; else return (n * factorial (n - 1)); }

Hmm. Five sets of brackets.

But I can hear some of you say there’s a better way. There is a more concise way, namely:

int factorial (int n) { return (n == 0) ? 1 : (n * factorial (n - 1)); }

Odd. That still has five.

No matter. In our C++ example, above, we end up with more than twice as many brackets to do a simple accumulator. In our C vs. Scheme factorial example we end up with Scheme having a couple of extra brackets. But not anything akin to the claims that there are way more.

In fact, I’m sure if we examined a lot of programs in C/C++, Java and Lisp/Scheme we’d realize that Lisp/Scheme has fewer brackets.

Now, a modern exception would be Python. It would end up with a couple of brackets. Much fewer than C or Scheme. Then again, we could opt for a modern Lisp like Arc and end up with three.

Thus, the arguments don’t hold water. In fact, I think the problem lies with the notation of Lisp, which is prefix. Ironically, that’s one of Lisp’s strengths. Everything is prefix. There are no weird infix vs. prefix rules to remember. Lisp always behaves the same way. It also allows for some fantastic ways of looking at things, like data, since it means that, from Lisp’s perspective, data and code are identical!

I doubt I’ll stop hearing about all the parentheses in Lisp anytime soon, but this little examination was quite interesting.

In the future, if I remember, I’ll probably comment on how much shorter Lisp programs usually are. Or, at worst, I’ll simply point to papers written by others that point out the difference. I think one of the papers I have lying about even shows that coding in Lisp is faster, substantially faster. And you’d think that would entice more people to try Lisp-like languages. However, I think what will get more people into Lisp is Clojure, which provides a Lisp that has the entire Java library set accessible as it runs atop the JVM and also provides elegant ways of dealing with multi-core processing. In the meantime, for the curious, I’ll point you to Norvig’s article on Java and Lisp. It’s enlightening.