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.

  • 1
    Have you tried using Lisp in a Lisp-aware environment like emacs? I wouldn't touch it any other way. – David Thornley Dec 9 '11 at 20:55
  • No I haven't, in which forms can it improve my Lisp experience? – vemv Dec 9 '11 at 20:58
  • writing short functions is also very important, although I've only done some playing with clojure. – Kevin Dec 9 '11 at 21:09
  • 3
    In a good Lisp environment, you ignore the parentheses and read the structure by the indentation. As you have noticed, reading the structure by counting parentheses is really, really annoying. – David Thornley Dec 9 '11 at 21:34

How do you parse

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

The parse tree probably looks something like

        left: a
        right: b
        name: foo
        param: param
      name: doSomething
      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))

Not too bad.

|improve this answer|||||
  • Lists are more versatile and powerful than exprs + statements no doubt. Trying Emacs (or what else?) is tempting but latest time I tried it just scared me a lot. What does sexp awareness bring exactly? – vemv Dec 9 '11 at 22:44
  • Simple stuff: they bounce a highlight on close and open parens (or highlight entire s-expressions differently). They have nice indenting rules. Emacs has other things, but they probably aren't as important for readability. There are other s-expression aware editors. You don't need emacs. If emacs scares you, try the bundles for textmate, sublime, etc. Once your editor starts helping with readability, things become a bit easier. I do most lispy stuff in racket, which allows square brackets anywhere parens could be used. Being able to switch up helps readability. – ccoakley Dec 9 '11 at 22:54
  • 1
    As an aside, make use of nested lets, defines, etc. break that stuff into smaller pieces. If you can't come up with a good name for a chunk, treat that as a warning about your design. Find the balance between too-small-to-name and too-big-to-read. – ccoakley Dec 9 '11 at 22:58
  • Oh that last advice is... memorable :) Trying Sublime as I'm writing this. – vemv Dec 9 '11 at 23:17

What's really nice about s-exp is that after a short period of time, you don't see them anymore, it's like python to your eyes BUT the computer still has the tree easily.

  • So indentation is automatic, there is no ambiguity, you don't have to press tab twice or something like that when you want to end a block.

  • If you pick some random code, the whole stuff is easily indented with just one command from your favorite editor

  • You can navigate through your code really easily, jump between s-exp, swap them and so on with a good editor

Plus, because the data you're manipulating are the same that the code you're writing, you could use the same language to manipulate your code right ?

Well, you can do it, that's what macros are, you manipulate the code you're writing before it is evaluated as like any others list, that's why it is said that Lisp is a "Programmable Programming Language". You write code that write your code for you.

Here is a nice article which describes the nature of Lisp and why Lisp programmers grinned when they see XML.

|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.