Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Why does the Lisp community prefer to accumulate all the parentheses at the end of the function:

(defn defer-expensive [cheap expensive]
  (if-let [good-enough (force cheap)]
    good-enough
    (force expensive)))

Why not employ a convention like C or Java?
Well ok, Lisp is much more older than those languages, but I'm talking about the contemporary Lispers.

(defn defer-expensive [cheap expensive]
  (if-let [good-enough (force cheap)]
    good-enough
    (force expensive)
  )
)

Note: Code snippet is from the book "The Joy of Clojure".

share|improve this question
4  
I'm told that back in the days of punch cards, it was common practice to end a Lisp program with an extra card with 80 right parentheses on it, just to make sure there were enough to match all of the open parentheses in the program. –  Alger Aug 8 '11 at 7:05
    
Wow, I like it. I've always hated the parenthesis, but your second example looks pleasant to me. Not as nice as Python, but improvement. –  Eric Wilson Aug 18 '11 at 18:20
1  
because they can? –  Muad'Dib Aug 19 '11 at 4:00
    
It would be nice if a dialect of Clojure promoted indentation to being code structure. That would do away with the parenthesis altogether (like F#, etc..). Of course, parenthesis would still be legal, if desired. –  Chris Nash Jun 2 '13 at 11:09
add comment

3 Answers 3

up vote 15 down vote accepted

One reason Algol-based languages encourage the braces on their own line is to encourage adding more lines in between the delimiting braces without having to move the braces. That is, if one starts out with

if (pred)
{
  printf("yes");
}

it's easy to come along and add another statement within the braces:

if (pred)
{
  printf("yes");
  ++yes_votes;
}

Had the original form been

if (pred)
{ printf("yes"); }

then we'd have to have "moved" two braces, but my example is more concerned with the latter. Here, the braces are delimiting what's intended to be a sequence of statements, mostly invoked for side effect.

Conversely, Lisp lacks statements; every form is expression, yielding some value—even if in some rare cases (thinking of Common Lisp), that value is deliberately chosen to be "no values" via an empty (values) form. It's less common to find sequences of expressions, as opposed to nested expressions. The desire to "open up a sequence of steps until the closing delimiter" doesn't arise as often, because as statements go away and return values become more common currency, it's more rare to ignore the return value of an expression, and hence more rare to evaluate a sequence of expressions for side effect alone.

In Common Lisp, the progn form is an exception (as are its siblings):

(progn
  (exp-ignored-return-1)
  (exp-ignored-return-2)
  (exp-taken-return))

Here, progn evaluates the three expressions in order, but discards the return values of the first two. You could imagine writing that last closing parenthesis on its own line, but note again that since the last form is special here (not in the Common Lisp sense of being special, though), with distinct treatment, it's more likely that one would add new expressions in the middle of the sequence, rather than just "adding another one on to the end," as callers would then be impacted not just by any new side effects but rather by a likely change in return value.

Making a gross simplification, the parentheses in most parts of a Lisp program are delimiting arguments passed to functions—just like in C-like languages—and not delimiting statement blocks. For the same reasons we tend to keep the parentheses bounding a function call in C close around the arguments, so too do we do the same in Lisp, with less motivation to deviate from that close grouping.

The closing of the parentheses is of far less import than the indentation of the form where they open. In time, one learns to ignore the parentheses and write and read by shape—much like Python programmers do. However, don't let that analogy lead you to think that removing the parentheses entirely would be worthwhile. No, that's a debate best saved for comp.lang.lisp.

share|improve this answer
    
i think that adding at the end is not that rare, e.g. (let ((var1 expr1) more-bindings-to-be-added) ...), or (list element1 more-elements-to-be-added) –  Alexey Oct 31 '13 at 19:51
add comment

Because it does not help. We use indentation to show code structure. If we want to separate blocks of code, we use really empty lines.

Since Lisp syntax is so consistent, the parentheses are the definitive guide to indentation for both the programmer and the editor.

(For me, the question is rather why C and Java programmers like to throw around their braces.)

Edit: Just to demonstrate, assuming that these operators were available in a C-like language:

Foo defer_expensive (Thunk cheap, Thunk expensive) {
    if (Foo good_enough = force (cheap)) {
        return good_enough; }
    else {
        return force (expensive); }}

Two closing braces close two nesting levels. The syntax is obviously correct. In analogy to Python syntax, the braces are just explicit INDENT and DEDENT tokens.

Of course, this might not be the "one true brace style"TM, but I believe that is just historic accident and habit.

share|improve this answer
2  
Also, almost all lisp editors mark the matching parenthesis when closing (some also correct ) to ] or vice versa), so you know you closed the right amount even if you don't check the indentation levels. –  configurator Aug 7 '11 at 16:25
4  
WRT "the question", because "throwing around" closing tokens in the style of the second example lets you easily line them up with your eyes and see what closes what, even if you're just in a text editor with no automatic matching/highlighting features. –  Mason Wheeler Aug 7 '11 at 16:31
1  
@Mason Wheeler Yes, Exactly. –  Chiron Aug 7 '11 at 21:07
2  
TBH, what this says to me is that the parens in LISP are mostly redundant, with the possibility (as with C++) that the indentation may mislead - if indentation tells you what you need to know it should tell the compiler the same thing too, as in Haskell and Python. BTW - having the braces at the same indent level as the if/switch/while/whatever in C++ helps prevent cases where the indentation is misleading - a visual scan down the LHS tells you that every open-brace is matched to a close-brace and that indentation is consistent with those braces. –  Steve314 Aug 8 '11 at 7:15
1  
@Steve314: No, the indentation is redundant. Indentation can mislead in Python and Haskell, too (think about one-off indentation or tabulars), it is just that the parser is mislead as well. I think that the parentheses are a tool for the writer and the parser, while indentation is a tool for the writer and the (human) reader. In other words, indentation is a comment, parentheses are syntax. –  Svante Aug 8 '11 at 8:55
show 2 more comments

The code is much more compact then. Movement in the editor is by s-expressions anyway, so you don't need that space for editing. Code is read mostly by structure and sentences - not by following delimiters.

share|improve this answer
    
What an honor to get an answer from you :) Thanks. –  Chiron Aug 18 '11 at 21:29
    
What editor moves by s-expressions? More specifically, how do I get vim to do that? –  hasenj Aug 19 '11 at 1:40
    
@HasenJ You might need the vimacs.vim plugin. :P –  Mark C Aug 27 '11 at 20:25
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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