From: ....What Is?....
Subject: Tradition Lisp code formatting
Date: 
Message-ID: <20899@sdcc6.ucsd.edu>
I wanted to post this a long time ago but feared starting a flame war.
But my curiosity has finally gotten the better of me.  I must know. :)

How did the traditional style of Lisp code turn out to be so crunched
together?

In languages like C, the trend has been to space everything out so
that blocks are visible (see GNU Emacs "c-mode" to see what I mean,
if you don't.)  I find it much more readable like that.  But in my
Lisp books, it seems, comparatively, smashed together!  Here's an
example, from page 115 of _Lisp: 3rd Edition_ by Patrick Henry
Winston and Berthold Klaus Paul Horn:

(defun count-outlyers (list-of-elements)
  (let ((result 0))
    (dolist (element list-of-elements
		     result)
    (when (or (> elements boiling)
	      (< element freezing))
      (setf result (+ result 1))))))

I would have formatted it this way:

(defun count-outlyers (list-of-elements)
    (let
	(
	    (result 0)
	)
	(dolist
	    (element list-of-elements result)
	    (when
		(or
		    (> element boiling)
		    (< element freezing)
		)
	        (setf result (+ result 1))
	    )
	)
    )
)

Whether to split and indent the (element list-of-elements result) is
usually a matter of whether or not the one-line version makes the
functionality immediately obvious, to me.  But to me, the functionality
of let seems much more obvious; the local variable "result" has been
created, and it's used inside a dolist.  (Incidentally, the only
reason I put the defun's argument list in the same line is so I can
do "grep '(defun' file.lisp" from csh to get a list of all the function
prototypes in the source file.)

So far, I've only found one other person who formats the way I do,
and he hates Lisp nowadays :-( so although it's not a very scientific
conclusion, I'd say there's at least a chance of programmers being
turned off by Lisp because they feel lost in all the parentheses and
cannot immediately divine the structure.  (He would get his Lisp
assignments back from the TA, re-formatted to the traditional way :)

I crossposted to a few seemingly unrelated newsgroups in the hopes
of finding people who were disenchanted with Lisp, to ask if this
was part of the reason.

Please give me your thoughts on this.  No Holy War(TM) intended. :-|

Steve Boswell         | This opinion is distributed in the hopes that it
······@ucsd.edu       | will be useful, but WITHOUT ANY WARRANTY...
······@gnu.ai.mit.edu |

From: Silver
Subject: Re: Tradition Lisp code formatting
Date: 
Message-ID: <Jun.23.08.57.04.1991.5234@brushfire.rutgers.edu>
······@gnu.ai.mit.edu writes:
> [Why is Lisp generally written so `tightly', rather than spaced out the way
>  one generally sees C et al?  I generally see Lisp written as it appears on
>  immediately below, and not as I prefer, which follows.
>
> (defun count-outlyers (list-of-elements)
>   (let ((result 0))
>     (dolist (element list-of-elements
> 		     result)
>     (when (or (> elements boiling)
> 	      (< element freezing))
>       (setf result (+ result 1))))))
>
> (defun count-outlyers (list-of-elements)
>     (let
> 	(
> 	    (result 0)
> 	)
> 	(dolist
> 	    (element list-of-elements result)
> 	    (when
> 		(or
> 		    (> element boiling)
> 		    (< element freezing)
> 		)
> 	        (setf result (+ result 1))
> 	    )
> 	)
>     )
> )
> ]

One reason may be the common misconception that whitespace is `cheap' or
`free'.  Too much whitespace can be as detrimental to readability as too
little.  This is especially true in the vertical direction, noting that
characters are generally taller than they are wide (for example, standard glass
terminals are ~24x80).

Note that the blocking structures of the two excerpts of code you provide are
not so different.  From your code samples, you claim preference for the style
on the left; standard lisp formatting is on the right.

    expression                          expression subexpression
        subexpression                              subexpression
        subexpression                              subexpression
        subexpression                              ...
        ...

The indentation format on the right is referred to as hanging indents, ie,
hanging the indentation for an expression off of the indent point for the
previous one, wherever it may be.  This style trades some vertical space for
horizontal, taking advantage of the less-used rightmost screen acreage.

This style is the general case.  But sometimes the right edge of the screen
creeps up a little too quickly, so skip to some small extra indentation on the
next line.  For example, the form on the left might have to be abandoned for
the one on the right, below.  (The right edge is indicated by pipes.)

    ...                     |           ...                     |
    (long-function-name 'bla|h          (long-function-name     |
                        'ble|tch          'blah                 |
                        'ble|chh)         'bletch               |
    ...                     |             'blechh)              |
                                        ...                     |

Also, there are times when the semantic differences of some of the leading
arguments should be emphasized to make them distinct from the remaining ones.
This is typical of special forms which control the flow of evaluation.  This
emphasis is usually shown by indenting them farther, or hanging their indents
and not hanging the indents of the remaining elements.  Hard to explain, easy
to show:

  (let ((variable value)                (let
        ...)                                ((variable value)
    bodyform                                 ...)
    ...)                                  bodyform
                                          ...)

The last item to address is the handling of closing parens across expressions
that span multiple lines.  You claim preference for putting them on their own
line indented at the same level as the matching open paren.  In your preferred
style, you dedicate 10 lines to single closing parens, making it over 2.4 times
as long as the other.  That's a LOT! of whitespace.  I can think of a few
reasons why this would be done.  The first is because it facilitates visual
matching.  But with smarter editors that blink match and move over balanced
expressions, that's no win.  The second is because it easier to move blocks of
code around.  That point I'll concede.

Regards, [Ag]
From: John Gateley
Subject: Re: Tradition Lisp code formatting
Date: 
Message-ID: <GATELEY.91Jun23134221@gefion.rice.edu>
In article <·························@brushfire.rutgers.edu> ······@brushfire.rutgers.edu (Silver) writes:

   [discussing reasons for putting one closing paren per line vs. all
   on one]
   The second is because it easier to move blocks of
   code around.  That point I'll concede.

I won't :^). Again, with smarter editors it is just as easy to move
blocks of code around with the dense representation. In particular,
the commands "move-forward-sexpression", "kill-sexpression" and
"reindent-sexpression" are great.

John
·······@rice.edu
--
"I've thought the thoughts of little children and the thoughts of men
 I've thought the thoughts of stupid people who have never been
 so much in love as they should be and got confused too easily
 to fall in love again." The Residents and Renaldo and the Loaf
From: Silver
Subject: Re: Tradition Lisp code formatting
Date: 
Message-ID: <Jun.23.14.30.16.1991.7985@brushfire.rutgers.edu>
I made the mistake of re-reading my own posting.

The format of some of the included code was slightly messed up because of the
author's use of some strange control character (ascii 9?) to indent the code.
[Frigging tabs are much more trouble than they were ever worth.  That's it.
I'm done with them.  In GNU Emacs, I'm setting indent-tabs-mode nil and adding
a hook to something, perhaps write-file, to warn me of their presence.]

As for editors, any editor of reasonable sophistication will blink matching
parens and compute hanging indents.  Determining when special indentation is
necessary is straightforward, but not run-of-the-mill.  [In GNU Emacs, see Info
on Lisp Indent, specifically, lisp-indent-offset and the lisp-indent-hook
property.]

Regards, [Ag]
From: Milt Epstein
Subject: Re: Tradition Lisp code formatting
Date: 
Message-ID: <2864C3CE.46E7@ibma0.cs.uiuc.edu>
In <·····@sdcc6.ucsd.edu> ········@sdcc13.ucsd.edu (....What Is?....) writes:

>I wanted to post this a long time ago but feared starting a flame war.
>But my curiosity has finally gotten the better of me.  I must know. :)
>
>How did the traditional style of Lisp code turn out to be so crunched
>together?

Well, I guess I consider myself a LISP programmer (common lisp) --
it's been the language I've used most the last few years, although I
have written some C stuff, and before that PASCAL -- so I'll offer
some comments -- although I don't have any amazing insights.


>In languages like C, the trend has been to space everything out so
>that blocks are visible (see GNU Emacs "c-mode" to see what I mean,
>if you don't.)  I find it much more readable like that.  But in my
>Lisp books, it seems, comparatively, smashed together!  Here's an
>example, from page 115 of _Lisp: 3rd Edition_ by Patrick Henry
>Winston and Berthold Klaus Paul Horn:
>
>(defun count-outlyers (list-of-elements)
>  (let ((result 0))
>    (dolist (element list-of-elements
>		     result)
>    (when (or (> elements boiling)
>	      (< element freezing))
>      (setf result (+ result 1))))))

For what it's worth, I would've done this function this way (assuming
it was common lisp):

(defun count-outlyers (list-of-elements &aux (result 0))
  (dolist (element list-of-elements result)
    (when (or (> elements *boiling*)
	      (< element *freezing*))
      (incf result))))

(BOILING and FREEEZING are global variables, I assume.)


>I would have formatted it this way:
>
>(defun count-outlyers (list-of-elements)
>    (let
>	(
>	    (result 0)
>	)
>	(dolist
>	    (element list-of-elements result)
>	    (when
>		(or
>		    (> element boiling)
>		    (< element freezing)
>		)
>	        (setf result (+ result 1))
>	    )
>	)
>    )
>)

Well, as you might expect, I find your first version (and my version
too, of course) much more readable and comprehendable than this second
one.  This second one seems much too spread out and has wasted space
-- when I say that, I mean space that doesn't necessarily help make
the code more readable.  I tried to think about why this might be so,
and came up with the following.

OK, what's the major difference between a language like LISP and a
language like C.  Well, LISP is functional programming and C is
imperative.  What are the consequences of this?  I think that the
goals of formatting are the same in each case (to make things more
readable), but they are realized differently due to the different
styles of the languages.

For one thing, what constitutes "blocks" of code differs.  In LISP,
the blocks will typically be indicated by separate functions, so they
are inherently distinct (and you'll have white space inbetween them).
In C, you may have distinct blocks within the same function (confusing
-- different use of the same term), so you may need to put white space
in to separate the blocks.

Another thing is that the relationship between one line of code and
the next differs.  In LISP, since everything is function calls, the
next line will probably be the arguments to a function call, so you'd
like to have them relatively close by to see what is going on.  In my
personal style (I'm not sure what other LISPers do), I tend to write
small functions, so they may often be only one function call (like a
let, dolist, cond, if), and it often turns out that everything is done
via nested function calls -- and then it seems like spreading things
out makes it harder to see what is going on.  This is the case in the
sample function you gave (and maybe that is why I don't like your
second version).  So, really, this function is just one line of code.
In C, different lines are usually distinct steps or commands, so they
don't need to be so close together.

I'll add that when I do occasionally write a program in C or PASCAL,
I do use this spread out style more, although I still tend to write
small functions.


>So far, I've only found one other person who formats the way I do,
>and he hates Lisp nowadays :-( so although it's not a very scientific
>conclusion, I'd say there's at least a chance of programmers being
>turned off by Lisp because they feel lost in all the parentheses and
>cannot immediately divine the structure.  (He would get his Lisp
>assignments back from the TA, re-formatted to the traditional way :)

I think any different language takes a little getting used to -- if
you just bear with it a little while and get more experience with it,
things will become easier.  Actually, I've TA'd a class that uses LISP
several times, and I've noticed a fair number of people that come from
a C-like background -- not just in the way they format, but in the way
they write the functions.  I've seen many a function formatted like
your second version above (and although I don't like it, I neither
re-format it nor deduct for it, although I do point out the preferred
style, which doesn't always make a difference :-).


>Please give me your thoughts on this.  No Holy War(TM) intended. :-|

What?!?!  You think you can start comparing C and LISP and not start a
holy war?!?!

:-)

-- 
Milt Epstein
Department of Computer Science
University of Illinois
·······@cs.uiuc.edu
From: John Gateley
Subject: Re: Tradition Lisp code formatting
Date: 
Message-ID: <GATELEY.91Jun24143442@gefion.rice.edu>
In article <·············@ibma0.cs.uiuc.edu> ·······@sunc2.cs.uiuc.edu (Milt Epstein) writes:

   [discussing formatting of Lisp]
   OK, what's the major difference between a language like LISP and a
   language like C.  Well, LISP is functional programming and C is
   imperative.

Auugh Auugh Auuugh! Lisp is NOT a functional programming language!!

A functional language is one without side-effects, and Lisp definitely
has side effects. I think what you meant to say was that the style in
Lisp was to package everything into functions, while C tends to
emphasize fewer (and larger) functions. Isn't terminology wonderful?

j
--
"I've thought the thoughts of little children and the thoughts of men
 I've thought the thoughts of stupid people who have never been
 so much in love as they should be and got confused too easily
 to fall in love again." The Residents and Renaldo and the Loaf
From: Gregory Snead
Subject: Re: Tradition Lisp code formatting
Date: 
Message-ID: <1991Jun25.203650.11389@MDI.COM>
In article <·····················@gefion.rice.edu>, ·······@rice.edu (John Gateley) writes:
|> In article <·············@ibma0.cs.uiuc.edu> ·······@sunc2.cs.uiuc.edu (Milt Epstein) writes:
|> 
|>    [discussing formatting of Lisp]
|>    OK, what's the major difference between a language like LISP and a
|>    language like C.  Well, LISP is functional programming and C is
|>    imperative.
|> 
|> Auugh Auugh Auuugh! Lisp is NOT a functional programming language!!
|> 
|> A functional language is one without side-effects, and Lisp definitely
|> has side effects. I think what you meant to say was that the style in
|> Lisp was to package everything into functions, while C tends to
|> emphasize fewer (and larger) functions. Isn't terminology wonderful?
|> 


I agree with you technically, but I still program as if LISP was a
functional language. In my opinion this makes my programs more
_correct_, at least in theory :{). I think the idea of LISP being
a functional language comes from its roots in lambda calculus. Perhaps
LISP was truly functional in its original conception.

=================================================================
(defun reply-address ()
   (print "A message for Gregory L. Snead") 
   
   (cond ((null (try-this-first ·····@mdi.com))
            (try-this-instead uunet!mdisea!snead) )
         (t (print "Sorry, bub! Talk to your Sys Admin")) )
)
=================================================================
 
From: David Tanguay
Subject: Re: Tradition Lisp code formatting
Date: 
Message-ID: <1991Jun23.190212.9552@watmath.waterloo.edu>
In article <·····@sdcc6.ucsd.edu> ········@sdcc13.ucsd.edu (....What Is?....) writes:
>How did the traditional style of Lisp code turn out to be so crunched
>together?
[... example showing a more blocky format than the traditional lisp...]

When I recently wrote my first non-trivial Scheme program I used a very
similar format (amazingly similar, I'm tempted to say). Not only did I find
it much more readable, it was also much easier to move code around with VI. 
-- 
David Tanguay                  ·········@watmath.waterloo.edu
Thinkage, Ltd.                 ···@Thinkage.On.CA
From: Richard A. O'Keefe
Subject: Re: Tradition Lisp code formatting
Date: 
Message-ID: <6472@goanna.cs.rmit.oz.au>
In article <·····@sdcc6.ucsd.edu> ········@sdcc13.ucsd.edu (....What Is?....) writes:
>How did the traditional style of Lisp code turn out to be so crunched
>together?
[... example showing a more blocky format than the traditional lisp...]

When I started out using Lisp I was using punched cards and a B6700.
I laid my Lisp code out just like my Algol code.
    (if <test>
	<then>
	<else>
    )
The thing that made the difference was that I eventually learned to READ
Lisp as well as to WRITE it.  I discovered that when reading good Lisp code
you ignore most of the parentheses.  It's up to the editor to make sure that
parentheses are balanced, I should just be looking at the words and the
layout.  Why highlight something that a fast reader isn't concerned with?
My Lisp layout conventions aren't _quite_ identical to the conventional
style, but they are a _lot_ closer than they used to be.
-- 
I agree with Jim Giles about many of the deficiencies of present UNIX.
From: David A Keldsen
Subject: Re: Tradition Lisp code formatting
Date: 
Message-ID: <1991Jun24.094106.24994@sq.sq.com>
········@watmath.waterloo.edu (David Tanguay) writes:

>In article <·····@sdcc6.ucsd.edu> ········@sdcc13.ucsd.edu (....What Is?....) writes:
>>How did the traditional style of Lisp code turn out to be so crunched
>>together?
>[... example showing a more blocky format than the traditional lisp...]

>When I recently wrote my first non-trivial Scheme program I used a very
>similar format (amazingly similar, I'm tempted to say). Not only did I find
>it much more readable, it was also much easier to move code around with VI. 

All you have to do to move Lisp code around in vi is to d% 
(or "ad% if you prefer).  Delete to the matching paren suffices...
then judicious use of P or p to paste it, and....voila!

(Who says lisp hackers don't use vi?)

Dak
-- 
David A. 'Dak' Keldsen of SoftQuad, Inc. email: ···@sq.com  phone: 416-963-8337
"You'd better get on with it," she said.  "That's fifty green fires and hot
leads to go, with a side order for blisters and scorpions.  Hold the mercy."
	-- _Sourcery_ by Terry Pratchett
From: Alan M. Carroll
Subject: Re: Tradition Lisp code formatting
Date: 
Message-ID: <1991Jun24.201228.11131@m.cs.uiuc.edu>
 In article <·····@sdcc6.ucsd.edu> ········@sdcc13.ucsd.edu (....What Is?....) writes:
>How did the traditional style of Lisp code turn out to be so crunched
>together?
> [... example showing a more blocky format than the traditional lisp...]

For anyone who likes the blocky style, you might want to check out my
Emacs lisp-mode extension in the Epoch distribution. Unfortunately, it
doesn't work in normal Emacs due to a bug in scan_sexps_forward()
(although I haven't tried it in 18.57).

-- 
Alan M. Carroll          <-- Another casualty of applied metaphysics
Epoch Development Team   
Urbana Il.               "I hate shopping with the reality-impaired" - Susan
From: John Gateley
Subject: Re: Tradition Lisp code formatting
Date: 
Message-ID: <GATELEY.91Jun23133724@gefion.rice.edu>
In article <·····@sdcc6.ucsd.edu> ········@sdcc13.ucsd.edu (....What Is?....) writes:

   [Why is lisp code so dense? Here's an example]

   (defun count-outlyers (list-of-elements)
     (let ((result 0))
       (dolist (element list-of-elements
			result)
       (when (or (> elements boiling)
		 (< element freezing))
	 (setf result (+ result 1))))))

I don't think your example is formatted correctly - the "when" should
be indented two more spaces.

   I would have formatted it this way:

   (defun count-outlyers (list-of-elements)
       (let
	   (
	       (result 0)
	   )
	   (dolist
	       (element list-of-elements result)
	       (when
		   (or
		       (> element boiling)
		       (< element freezing)
		   )
		   (setf result (+ result 1))
	       )
	   )
       )
   )

First, a major point: I want to fit as much code on the screen as
possible. If your function is small (as many lisp functions are), I
want to see as many of the other functions that it calls as possible.
If your function is large (and some are) I want to see as much of the
context as possible. So, I hate the paren style you use. This is why
the dense style has developed, I think. It just struck me - though
people commonly get print-outs of pascal/C/<pick your favorite
language> program to read, I almost never read lisp code that way - I
always do it with a text editor.

Second, the block structure is just as obvious to me in the first
example as the second (modulo the problem I mentioned). If you have
lots of code, all you need to do is look at the indentation of the
next line to figure out which blocks have ended etc. It may take a
little practice to get used to, but it's worth it. You may be
concerned about errors in indentation, which can cause major problems.
However, most (some? a privileged few?) people rely heavily on their
text editors for writing lisp programs: flashing matching parenthesis,
moving forward or backwards to the matching parenthesis, automatic
indentation etc. I really like the automatic indentation feature: just
hit return and your automatically at the right spot! It makes for
fewer errors, and when you make a major (structural) change, there is
a command which reindents a whole s-expression.

   Whether to split and indent the (element list-of-elements result) is
   usually a matter of whether or not the one-line version makes the
   functionality immediately obvious, to me.

My only criteria here is to put as much on one line as possible,
without forcing subsequent lines to have too much indentation. Of
course, I don't write:
(progn (foo) (setq x 4) (bar (- x 6)) (baz (+ (bar 3) 5) (bum)))
but only do it within reason. I am careful to avoid lines which
will cause subsequent lines to be indented a lot. I would avoid:
(let ((x (let ((y 4))
           <some-complex-expression>)))
  ...)
and instead use:
(let
  ((x
    (let ((y 4))
      <some-complex-expression>)))
  ...)
This, as another poster pointed out, is trading horizontal space for
vertical space.

John
·······@rice.edu
--
"I've thought the thoughts of little children and the thoughts of men
 I've thought the thoughts of stupid people who have never been
 so much in love as they should be and got confused too easily
 to fall in love again." The Residents and Renaldo and the Loaf
From: Darryn Kozak
Subject: Re: Tradition Lisp code formatting
Date: 
Message-ID: <124942.14634@timbuk.cray.com>
In article <·····@sdcc6.ucsd.edu>, ········@sdcc13.ucsd.edu (....What Is?....) writes:
> I wanted to post this a long time ago but feared starting a flame war.
> But my curiosity has finally gotten the better of me.  I must know. :)
> 
> How did the traditional style of Lisp code turn out to be so crunched
> together?
> 
> In languages like C, the trend has been to space everything out so
> that blocks are visible (see GNU Emacs "c-mode" to see what I mean,
> if you don't.)  I find it much more readable like that.  But in my
> Lisp books, it seems, comparatively, smashed together!  Here's an
> example, from page 115 of _Lisp: 3rd Edition_ by Patrick Henry
> Winston and Berthold Klaus Paul Horn:
> 
> (defun count-outlyers (list-of-elements)
>   (let ((result 0))
>     (dolist (element list-of-elements
> 		     result)
>     (when (or (> elements boiling)
> 	      (< element freezing))
>       (setf result (+ result 1))))))
> 
> I would have formatted it this way:
> 
> (defun count-outlyers (list-of-elements)
>     (let
> 	(
> 	    (result 0)
> 	)
> 	(dolist
> 	    (element list-of-elements result)
> 	    (when
> 		(or
> 		    (> element boiling)
> 		    (< element freezing)
> 		)
> 	        (setf result (+ result 1))
> 	    )
> 	)
>     )
> )
> 
> Whether to split and indent the (element list-of-elements result) is
> usually a matter of whether or not the one-line version makes the
> functionality immediately obvious, to me.  But to me, the functionality
> of let seems much more obvious; the local variable "result" has been
> created, and it's used inside a dolist.  (Incidentally, the only
> reason I put the defun's argument list in the same line is so I can
> do "grep '(defun' file.lisp" from csh to get a list of all the function
> prototypes in the source file.)
> 
> So far, I've only found one other person who formats the way I do,
> and he hates Lisp nowadays :-( so although it's not a very scientific
> conclusion, I'd say there's at least a chance of programmers being
> turned off by Lisp because they feel lost in all the parentheses and
> cannot immediately divine the structure.  (He would get his Lisp
> assignments back from the TA, re-formatted to the traditional way :)
> 
> I crossposted to a few seemingly unrelated newsgroups in the hopes
> of finding people who were disenchanted with Lisp, to ask if this
> was part of the reason.
> 
> Please give me your thoughts on this.  No Holy War(TM) intended. :-|
> 
> Steve Boswell         | This opinion is distributed in the hopes that it
> ······@ucsd.edu       | will be useful, but WITHOUT ANY WARRANTY...
> ······@gnu.ai.mit.edu |


I prefer the "smashed" look myself, both for Lisp and C. And there's no need for a Holy War, because I'm right (just a joke folks).

	Have a nice day,

	Darryn J Kozak

	Cray Research Park
	655F Lone Oak Drive
	Eagan, MN  55121
	USA

	······@cray.com

	(612) 683-5244

	ISS (Integrated Support System) Project


	
From: Jeff Dalton
Subject: Re: Tradition Lisp code formatting
Date: 
Message-ID: <5016@skye.ed.ac.uk>
In article <·····@sdcc6.ucsd.edu> ········@sdcc13.ucsd.edu (....What Is?....) writes:
>In languages like C, the trend has been to space everything out so
>that blocks are visible (see GNU Emacs "c-mode" to see what I mean,
>if you don't.)  I find it much more readable like that.  But in my
>Lisp books, it seems, comparatively, smashed together!

The essential idea behind Lisp code formatting is to make it
unnecessary to pay attention to individual parentheses when
reading code.  The C-like style that places lots of close
parens alone on a line makes the individual parens more
significant.

Moreover, in C individual parens aren't put along on a line.
It's { and } that are treated that way.  That doesn't work so
well in Lisp, perhaps because parens are used so often and { }
is too close visualy to ( and ).  However, some Lisp programmers
mix ( ) and [ ] in their code, eg:

   (let ([var1 expr1]
         [var2 expr2])
     ...)

-- Jeff