Hacker News new | past | comments | ask | show | jobs | submit login
Examples of Lisp formatting through history (kazimirmajorinc.blogspot.com)
107 points by hadronzoo on March 9, 2012 | hide | past | favorite | 43 comments



Interesting. Two trends I pick up on at glance: 1) increased use of indentation 2) abandoning commenting for self-documenting code (and the occasional header comment). I'm guessing these are pretty universal trends, no?


Coding in Haskell changed the way I indent Lisp code. The way I intent now differs from most Lisp indentation styles in that

  (a (b (c (d (e
    (f (g (h xxx yyy (i uuu (vv ww qq) (j
      foo bar))))))))))
becomes allowed whereas

  (let ((a b)
        (c d))
    foo)
becomes not allowed -- you have to write it as

  (let
    ((a b)
      (c d))
    foo)
or (if you need the let clauses to line up) as

  (let
    (
      (a b)
      (c d))
    foo)
Well, the let form is such a unusual case that I will give a second example:

  (f (g xxx
        yyy)
     zzz)
becomes not allowed -- you have to write it as

  (f
    (g xxx
      yyy)
    zzz)
or (if you need g's arguments to line up) as

  (f
    (g
      xxx
      yyy)
    zzz)
Although I used two spaces for every new level of indentation above, the choice of the number 2 is of course not an essential element of the style.


That seems pretty strange, and some of those examples are really hard to read. Care to share some real Lisp code and not just (a (b (c ... ))) examples? And maybe some motivating examples in Haskell? I just can't see how any of these are an improvement and I'm curious.


In Haskell it is not uncommon to see things like

  foo x y = x >>= \a -> case a of
    Leaf -> ..
    Branch aleft aright -> ..
which translates into the Scheme pseudocode

  (define (foo x y) (bind x (lambda (a) (case a
    ((leaf) ..)
    (branch aleft aright) ..)
Although such an indentation pattern (namely, multiple "unclosed" open parens on one line, which all get closed at once) is very uncommon in Scheme or Lisp code, I find it handy enough to trade off for certain other "competing" indentation patterns (namely, the one in the final example in grandparent) traditional in Scheme and Lisp.

I have been meaning to put my .emacs.d (5800 lines) on Github. Do you want me to email you when I have done so?


    foo x y = x >>= \a -> case a of
        Leaf -> ..
        Branch aleft aright -> ..
Hanging lambdas yes, but I don't see the advantage of putting the beginning of the case into the same line.

    foo x y = x >>= \a ->
        case a of
             Leaf                -> ..
             Branch aleft aright -> ..
But the example is a bit contrived, because you could write it this way:

    foo x y = do
        a <- x
        case a of
             Leaf                -> ..
             Branch aleft aright -> ..


We must have different goals for our choice of indentation style: my goal is to minimize lines of code while preserving readability.

(Not lining things up as in

  (f xxx
    yyy)
initially detracts from readability, but in my experience with the new style, readability goes back up to very close to where it was as I get used to the new style.)


I actually like the first one best, and would prefer a case-lambda even more. Once it becomes available we can write

  foo x y = x >>= \case
    Leaf -> ..
    Branch l r -> ..
modulo whatever syntax gets chosen. That would save an unnecessary temporary variable. (See https://groups.google.com/group/haskell-cafe/browse_thread/t...)

Temporary variables clutter up the name space. While reading code you have to look for shadowing, or whether that variable is ever used again.


Agree about case lambda (and consequently that I could have chosen a better example).


That makes much more sense given the snippet of Haskell and isn't so hard to read. No need to email though, I'm pretty happy with the standard Lisp indentation style. Thanks for clarifying.


You are welcome.

By the way, any Emacker who shares my skepticism of the value of the traditional Emacs practice of having special indentation amounts for certain special forms and who prefers a slightly more regular/boring indentation style can get the TAB key to reflect that skepticism/preference with (setq lisp-indent-offset 2) and (setq lisp-body-indent 2) (or (setq lisp-indent-offset 4) and (setq lisp-body-indent 4) or such).

Disclaimer: untested on Emacs 23 or 24. (I'm still on Emacs 22.)


Does that happen because Haskell has significant whitespace? I suppose you might get used to the way it requires you to line things up and come to like it.

    (let 
       ((a b)
         (c d))
       foo)
Seems odd to me because the (a b) and (c d) are semantically the same but can't line up. Or, they can't line up without spending a new line on each function call, as if this were Java or something.

Don't worry; I know Haskell isn't Java-like. (Haskell is Python plus Perl: Significant whitespace plus polymorphism based on external context of the expression. Written in the APL charset.)


>Does that happen because Haskell has significant whitespace?

You can do the same thing in Lisp and Scheme, where of course whitespace is not significant.

If you're asking if Haskell's significant whitespace somehow made it more probable that programmers would do it, the answer is, I do not know.


Your comment got me wondering if you could make whitespace significant in Lisp - perhaps via a reader macro....


From what you're presenting here, you're using significantly more vertical than other lispers generally. Why is this preferable to rainbow parens, ShowParenMode or parenFace (there's probably lots of other paren highlighters for emacs), to match open/closing delimiters?


I disagree that my style uses more vertical: it has one change that increases vertical and one that reduces it, and no one has done an analysis to determine the net effect.


What's wrong with that?

  (let ((a b)
        (c d))
    foo)
I often write my lets and wheres in Haskell as

  let a = b
      c = d
  in foo
and have seen that style in other people's code, too.


inconsequential indent level. Makes it impossible to analyze algorithms at a glance. If you are consequent about your indent levels and get a lot of experience writing code like that, you can glance over a piece of text, notice the main keywords and indent levels, and you immediately have a good idea of what the code might be doing.


You make a good argument for choosing one style and sticking to it, but I don't see how it helps you choose between the different styles here.


i'm not sure think your personal take on lisp indentation has any compelling benefits to justify departing from consensus.

i recognize a lot of old school lispers follow a philosophy of "lisp empowers me so much that i don't need a team", so they do whatever they want and their productivity so godly that nobody says anything, but this isn't particularly helpful to increased lisp adoption, which benefits us all. maybe it isn't harmful either, but we who are already using it aren't in a position to judge this.


Good points. (I have not yet distributed significant amounts of Lisp code, and if I started, I'd probably stick to a conventional style or make it very clear that the distribution is just a dump of something coded just to scratch my own itch.)


What are you talking about, he's using standard banner-style-indent with lisp-close-brackets (i.e. the closing brackets are on the last line of the body, not below the body)

I use banner style in all languages and it works well.


In that case, if you use Emacs, perhaps you'd like to see the Emacs Lisp that I have bound to my tab key (which however has not been made to work with non-Lisp-syntax languages).

If you write "(a (b (c (d (e (f" RET, TAB indents just as many spaces as it would if you had written just "(a" RET.


Sounds cool. I don't use emacs at all, but maybe you can post it anyways?


Now that I know you see replies to your comments, I will inform you that I disagree with your assertion that what I have been describing here is just banner style.

Lisp coders are accustomed to a certain pattern of indentation that would be analogous to the following in C, where xxx and yyy are typically many lines long:

  while(aa){if(bb){
                xxx}
      yyy}
I am recommending for Lisp coders to avoid that pattern and to indent the above as follows:

  while(aa){
      if(bb){
          xxx}
      yyy}
which is of course familiar to a C programmer and which we will refer to as "formula A". However, what will be unfamiliar to a C programmer is the motive behind my recommendation: namely, to make it possible to introduce into Lisp a new pattern of indentation, unfamiliar to C programmers and Lisp programmer (but familiar to Haskell programmers) in which you are allowed to write,

  while(aa){if(bb){
      xxx}}
where again xxx is a place holder for many lines of code. However, it is important to note that the following would be a definite violation of the indentation style I recommend:

  while(aa){if(bb){
      xxx}
      yyy}
I recommend indenting that as formula A above. In other words, you can begin multiple multi-line s-expressions on the same line, but if you do, you have to close all of those multi-line s-expressions at the same time.

>maybe you can post it anyways?

It's a little too long: about 90 lines of code. I could make it shorter by taking out the code that warns the user of the stylistic violation described above, but most user would want that code.


i'm quite confused, I'd love to read a blog post with side-by-side examples in both C-style and lisp, in both styles, laying out the benefits.


What you just described totally is banner style. Don't fool yourself! You're just reducing lisp's indent idiocy to something easier to use. Indent I have seen described as "lisp style" (and there are many kinds) can never be called banner-style. Banner style's most important rule is that a new block that should stand out is given one extra indent level, as a whole, except for the header. Lisp style's most important rule is that things that lists of things should have their first element in the header, and the next elements should graphically be right under the first thing, never mind formatting and other things like that. Those concepts are in no way compatible.

Anyways, this:

    while(aa){if(bb){
        xxx}
        yyy}
is not banner-style indent, whereas this:

    while(aa){
        if(bb){
            xxx}
        yyy}
is.

It's a little too long: about 90 lines of code

Not too long for Bitbucket.

This "lisp style indenting" happens in Haskell every now and then too -- luckily all the big projects I looked at use fixed size indent. It's usually a sign of a programmer who hasn't written a lot of code, but I bet someone reading this will find some guy as good as Simon Marlow doing exactly that.


I wrote my own indenter in EMACS for clojure 'cause I don't like the standard indentation of modern lisps. My indenter uses the "primitive" syntax-level indentation exemplified by the "Dream of a lifetime" code example from 1979 on this page.

This is the ONE AND ONLY CORRECT INDENTATION STYLE for Lisp.


This is the ONE AND ONLY CORRECT INDENTATION STYLE for Lisp.

Because the defining feature of Lisp is allowing only one way to do things?


More like arguing about the one right way to do things. And if no one agrees, write your OWN Lisp.


I thought the defining feature of Lisp was the meta-programming. Or am I missing some sarcasm?


Yes, lemming's comment is sarcastic.


Look at all the commas!

Clojure has been ahead of the curve on these commas, of course. Commas (and semicolons) are considered whitespace. They're available to pretty up your code's presentation however you like. It's like Clojure is committing in advance not to need many syntax characters.


Ahead of the curve? Other Lisps stopped using commas half a century ago.


Link to the last example, from "Introduction to Newlisp, wikibook, 2012":

http://en.wikibooks.org/wiki/Introduction_to_newLISP/Macros#...


Is this the definite proof that Lisp in unreadable, no matter what?


The standard joke about how Lisp looks, which I believe comes from Perl's Larry Wall, is "oatmeal and toenail clippings".

It's interesting to see the old ones even if one is not a big lisp fan, though.


A very cool history of Lisp: while we see the changes in formatting styles over the years, we also see the personalities behind the progress of Lisp. Really nice!


Not all samples have numbers in them, but I was somwhat disturbed that it was not until 2012 that the LISP publishers used a monospace font that clearly distinguished 0 "zero" and O "capital letter o".


A number of the documents he excerpted are available via http://www.softwarepreservation.org/projects/LISP/ .


This is almost impossible to read on an iPhone. The text doesn't resize and whenever I try to scroll around it activates some blogger "next article" functionality


Likewise on an Android. Made for difficult reading.


That was fun, but he missed InterLisp D. I got an Xerox 1108 Lips Machine in 1982, and InterLisp D was amazing!





Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: