sboswell@sdcc13.ucsd.edu (....What Is?....) (06/23/91)
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 whatis@ucsd.edu | will be useful, but WITHOUT ANY WARRANTY... whatis@gnu.ai.mit.edu |
gaynor@brushfire.rutgers.edu (Silver) (06/23/91)
whatis@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]
epstein@sunc2.cs.uiuc.edu (Milt Epstein) (06/23/91)
In <20899@sdcc6.ucsd.edu> sboswell@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 epstein@cs.uiuc.edu
gateley@rice.edu (John Gateley) (06/24/91)
In article <Jun.23.08.57.04.1991.5234@brushfire.rutgers.edu> gaynor@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
gateley@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
gaynor@brushfire.rutgers.edu (Silver) (06/24/91)
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]
datangua@watmath.waterloo.edu (David Tanguay) (06/24/91)
In article <20899@sdcc6.ucsd.edu> sboswell@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 datanguay@watmath.waterloo.edu Thinkage, Ltd. dat@Thinkage.On.CA
ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (06/24/91)
In article <20899@sdcc6.ucsd.edu> sboswell@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.
dak@sq.sq.com (David A Keldsen) (06/24/91)
datangua@watmath.waterloo.edu (David Tanguay) writes: >In article <20899@sdcc6.ucsd.edu> sboswell@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: dak@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
gateley@rice.edu (John Gateley) (06/25/91)
In article <2864C3CE.46E7@ibma0.cs.uiuc.edu> epstein@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
dkozak@mahogany29.cray.com (Darryn Kozak) (06/25/91)
In article <20899@sdcc6.ucsd.edu>, sboswell@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 > whatis@ucsd.edu | will be useful, but WITHOUT ANY WARRANTY... > whatis@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 dkozak@cray.com (612) 683-5244 ISS (Integrated Support System) Project
carroll@cs.uiuc.edu (Alan M. Carroll) (06/25/91)
In article <20899@sdcc6.ucsd.edu> sboswell@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
snead@MDI.COM (Gregory Snead) (06/26/91)
In article <GATELEY.91Jun24143442@gefion.rice.edu>, gateley@rice.edu (John Gateley) writes: |> In article <2864C3CE.46E7@ibma0.cs.uiuc.edu> epstein@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 snead@mdi.com)) (try-this-instead uunet!mdisea!snead) ) (t (print "Sorry, bub! Talk to your Sys Admin")) ) ) =================================================================
jeff@aiai.ed.ac.uk (Jeff Dalton) (06/26/91)
In article <20899@sdcc6.ucsd.edu> sboswell@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