Lisp Code Formatting
Asked Answered
B

5

38

One of the people who took the time to comment on my other question about Clojure/LISP syntax pointed out that I had not written my sample code in the standard LISP way. So he was kind enough to rewrite the code snippet and that's a big help. But it raised another question in my mind. Why would this:

(if (= a something)
  (if (= b otherthing)
    (foo)))

which is standard LISP formatting be preferrable to this form:

(if (= a something)
  (if (= b otherthing)
    (foo)
  )
)

which is the way I would have naively formatted this code because of my C++ development background. I'm wondering if there's any benefit to the latter formatting or it's just an entrenched standard (like a QWERTY keyboard). I'm not trying to be argumentative--it's just difficult for me to understand why the first form would be preferable. The second form helps me to see the code structure more easily.

Busiek answered 12/2, 2009 at 14:15 Comment(1)
Instead of <pre>(if (= a something) (if (= b otherthing) (foo))) </pre> You might want to consider <pre> (when (and (= a something) (= b otherthing)) (foo)) </pre>Numbers
S
41

The closing parentheses on extra lines don't really help with seeing the structure of the code, because you can get the same information from the level of indentation. However, the second form takes up almost twice as many lines, forcing you to scroll more often when reading code.

And if you need to inspect the nested parentheses more closely, an editor that highlights the matching parenthesis will help you. This will also be easier when the matching parenthesis is not too far away.

If expressions get too long and complicated to be easily read, it may also be a sign that you should extract part of the functionality into a separate function.

Sobriety answered 12/2, 2009 at 14:35 Comment(0)
D
37

The way Lisp code is indented is sort of like the significant whitespace in Python, except that it's of course optional. The basic rule of thumb is that you place items in a list underneath one another vertically if they're not on the same line.

(a (b (c (d e)
         (f g))
      (h i j))
   (k l m n))

Without even looking at the parenthesis, you can see that (d e) and (f g) are parameters for c, (c (d e) (f g)) and (h i j) are parameters for b, and (b (c (d e) (f g)) (h i j)) and (k l m n) are parameters for a.

With your example, it should more correctly be formatted as follows:

(if (= a something)
    (if (= b otherthing)
        (foo)))

    ^   ^
  notice how they line up

Now that the level of indent becomes meaningful, you no longer have to rely on balancing parenthesis to get that information, and since it's more compact to put them on the same line as the closing statement, that's what lispers do. Granted, it's not required that Lisp code be formatted this way, but it's a fairly standard convention that people use and can rely on.

Doy answered 12/2, 2009 at 14:24 Comment(5)
Good point about whitespace and Python. You can regard the parentheses as helpers for your editor to determine indentation, and ignore them otherwise. Incidentally, when you get used to Lisp, you will not "see" them anymore.Devaughn
I agree that your way of indenting IF forms is both more conventional and esthetically preferable to the OP's way as far as Lisp as a language family is concerned, but the OP's way is, in fact, (and slightly unfortunately so, in my opinion) the Clojure convention.Torr
Funny thing, I just checked Emacs and it indents like the OP with IF, but with a random name it indents like I did above. Maybe there's something special with IF, but the inconsistency is annoying.Doy
the different indent for IF is because 'foo' is what happens if the condition holds and is as such not a parameter of IF.Rhabdomancy
FWIW, i've seen Java coding standards that required closing curlies to be placed on the same line, much in the same manner.Nicolenicolea
T
3

The simple answer is that your way isn't the way that Lisp's pretty-printer does things. Having ONE TRUE FORMAT is always a good thing for code, and the pprint macro gives you that format built into the language.

Of course, because the pprint macro exists, it's not strictly necessary for you to follow standard code formatting, because people can just run your code through pprint and get what they're used to. However, since everyone else uses pprint, or manually approximates it, you'll have a hard time reading code if you don't do it the same way, and you don't have an easy macro that will turn their code into your preferred format.

Traditionalism answered 23/2, 2009 at 15:55 Comment(0)
S
1

You can reformat Lisp code with the package Sreafctor: Homepage.

Some demos:

Available Commands:

  • srefactor-lisp-format-buffer: format whole buffer
  • srefactor-lisp-format-defun: format current defun cursor is in
  • srefactor-lisp-format-sexp: format the current sexp cursor is in.
  • srefactor-lisp-one-line: turn the current sexp of the same level into one line; with prefix argument, recursively turn all inner sexps into one line.

The formatting commands are usable on Common Lisp and Scheme as well.

If there is any problem, please submit an issue report and I will be happy to fix it.

Sexagenarian answered 8/4, 2015 at 10:12 Comment(0)
A
0

When you have 10 parentheses to close, it becomes really clunky.

When I used to program Lisp I left a space between the closing parentheses for opening parentheses on the same line and the rest, to simplify counting, like this:

(if (= a something)
  (if (= b otherthing)
    (foo) ))

I guess these days that is no longer needed, as editors are more helpful.

Angleaangler answered 12/2, 2009 at 14:20 Comment(4)
I think that's a helpful convention; I'll have to try it out. It can really help with code under frequent editing, as you can see where the linesplit should go.Barranca
That's horrible advice, really.Tolyl
What's so horrible about it?Angleaangler
There is an example in The LISP 1.5 Programmer's Manual from 1962: kazimirmajorinc.blogspot.de/2012/03/…Angleaangler

© 2022 - 2024 — McMap. All rights reserved.