As a newbie to Lisp, I am interested in (among other things) programming style differences between C/C++/Java and Lisp. For instance Kantrowitz and Margolin write, "Don't write Pascal (or C) code in Lisp. ... Don't put a close parenthesis on a line by itself -- this can really irritate programmers who grew up on Lisp."
I'm not so sure that this is a rational preference. So let me defend the 'C style' and invite all Lisp mavens to set me straight. Here is a small practice fragment I used just to fool around:
;;; Display a list using NTH ;;; Lisp style code (let ((L (list 'a 'b 5 'symbol -14))) (dotimes (i (length L)) (print (nth i L))))
;;; Same code - C style (let
(L (list 'a 'b 5 'symbol -14)) ) (dotimes (i (length L)) (print (nth i L)) ) )
Why prefer the C style? Well, say I later want to add more forms to the DOTIMES body. With the Lisp Style I have to analyze what belongs to what before inserting the form between the 2nd and third closing parentheses -- Easy to mess up, even in relatively simple code like this.
With the 'C style', however, the indentation and parenthesis placement does the work for me, allowing me to add new forms or delete existing ones, 1 per line, to the DOTIMES body (or to the LET body) without worrying about parentheses. The same goes for adding new bindings or removing old ones.
One goal of programming style is to facilitate code changes. In this regard, the C style weds function and form in a way the Lisp style does not.
"Roy Mash" <Roy_M...@ci.sf.ca.us> writes: > As a newbie to Lisp, I am interested in (among other things) programming > style > differences between C/C++/Java and Lisp. For instance Kantrowitz and > Margolin write, > "Don't write Pascal (or C) code in Lisp. ... Don't put a close > parenthesis on a line by itself -- > this can really irritate programmers who grew up on Lisp."
> I'm not so sure that this is a rational preference. So let me defend the 'C > style' and invite all > Lisp mavens to set me straight. Here is a small practice fragment I used > just to fool around:
> ;;; Display a list using NTH > ;;; Lisp style code > (let ((L (list 'a 'b 5 'symbol -14))) > (dotimes (i (length L)) > (print (nth i L))))
> ;;; Same code - C style > (let
> (L (list 'a 'b 5 'symbol -14)) > ) > (dotimes (i (length L)) > (print (nth i L)) > ) > ) > Why prefer the C style? Well, say I later want to add more forms to > the DOTIMES body. With the Lisp Style I have to analyze what belongs > to what before inserting the form between the 2nd and third closing > parentheses -- Easy to mess up, even in relatively simple code like > this. > With the 'C style', however, the indentation and parenthesis > placement does the work for me, allowing me to add new forms or > delete existing ones, 1 per line, to the DOTIMES body (or to the LET > body) without worrying about parentheses. The same goes for adding > new bindings or removing old ones.
If you need to add additional code inside the DOTIMES body, you just need to stick the cursor at what _appears_ to be an appropriate spot, and press enter.
If you got the right spot, then the cursor will sit at the spot you expect, thusly:
(let ((L (list 'a 'b 5 'symbol -14))) (dotimes (i (length L)) (print (nth i L)) )) ^--- Cursor sits here
If you positioned the cursor wrongly, then you'll get one of the following:
(let ((L (list 'a 'b 5 'symbol -14))) (dotimes (i (length L)) (print (nth i L) )))
(let ((L (list 'a 'b 5 'symbol -14))) (dotimes (i (length L)) (print (nth i L))) )
It's pretty obvious, by inspection, which position is the right one; if you get it wrong, it's easy enough to c-u c-b Enter or c-u c-f Enter to fix it up.
There's a much more important benefit to the "traditional approach:" your indentation appproach results in three lines of code expanding to fill up 9 lines of screen space.
For me to buy a screen three times as large as the one I've got would likely cost me the price of a Lexus automobile.
The notion of wasting that much screen space because I _might_, _someday_, want to add additional code is what strikes me as nearly criminal.
It's just _idiocy_ to waste lines for ONE PARENTHESIS. -- (concatenate 'string "cbbrowne" "@ntlug.org") http://vip.hyperusa.com/~cbbrowne/unix.html Pound for pound, the amoeba is the most vicious animal on earth.
"Roy Mash" <Roy_M...@ci.sf.ca.us> writes: > Why prefer the C style? Well, say I later want to add more forms to the > DOTIMES body. With the Lisp Style I have to analyze what belongs to > what before inserting the form between the 2nd and third closing > parentheses -- Easy to mess up, even in relatively simple code like this.
Not if you're using a good text editor. Emacs has commands that hop over balanced parens, that tell you when parens match, that open up new space on a fresh line and indent to the right place at the same time. It is VERY hard to mess up if you're using a competent Lisp-savvy text editor.
> One goal of programming style is to facilitate code changes. In this regard, > the C style weds function and form in a way the Lisp style does not.
You're using the wrong text editor. We all see this as a goal, too, but we also like to see a reasonable amount of code on a screen and the C style means we only see about a half to a third as much code per screen, while buying us (who use good text editors) none of the advantages you want, since we already have them.
PLEASE check out Emacs and its Lisp mode, or an equivalent editor such as comes on the Lisp Machine (Zmacs), in Macintosh MCL (FRED), or in Xanalys LispWorks (boringly called the Editor).
> As a newbie to Lisp, I am interested in (among other things) programming > style > differences between C/C++/Java and Lisp. For instance Kantrowitz and > Margolin write, > "Don't write Pascal (or C) code in Lisp. ... Don't put a close > parenthesis on a line by itself -- > this can really irritate programmers who grew up on Lisp." > I'm not so sure that this is a rational preference. So let me defend the 'C > style' and invite all > Lisp mavens to set me straight. Here is a small practice fragment I used > just to fool around:
> ;;; Display a list using NTH > ;;; Lisp style code > (let ((L (list 'a 'b 5 'symbol -14))) > (dotimes (i (length L)) > (print (nth i L))))
The nice thing about the above code is that the parens are essentially invisible. You don't worry about them, and you get into the habit of ignoring them.
> ;;; Same code - C style > (let
> (L (list 'a 'b 5 'symbol -14)) > ) > (dotimes (i (length L)) > (print (nth i L)) > ) > )
The major problem with the above code is that it is hard to see the actual code for all of the parentheses screaming "look at me!". The parens are definitely not invisible in the above code.
> Why prefer the C style? Well, say I later want to add more forms to the > DOTIMES body. With the Lisp Style I have to analyze what belongs to > what before inserting the form between the 2nd and third closing > parentheses -- Easy to mess up, even in relatively simple code like this.
Again, you're looking at parentheses. Don't do that. Look at expressions instead. If your editor is lisp-savvy, it will allow you to traverse into, out of, and across expressions very easily.
> With the 'C style', however, the indentation and parenthesis placement > does the work for me, allowing me to add new forms or delete existing ones, > 1 per line, to the DOTIMES body (or to the LET body) without worrying > about parentheses. The same goes for adding new bindings or removing old > ones.
The C style is a line-oriented style. Even source-level debuggers don't tend to see with any finer granularity than the line. In Lisp, the expression is the preferred unit of syntax, not the line.
> One goal of programming style is to facilitate code changes. In this regard, > the C style weds function and form in a way the Lisp style does not.
No, the C style weds line-orientation to the code. If you look at your C style lisp code above, you have essentially made it more line-by-line editable by breaking up the major expressions so that they are on their own lines. Code changes are easy to make in an expression-oriented indentation if you learn how to manipulate expressions in your editor as well as you already know how to manipulate lines.
-- Duane Rettig Franz Inc. http://www.franz.com/ (www) 1995 University Ave Suite 275 Berkeley, CA 94704 Phone: (510) 548-3600; FAX: (510) 548-8253 du...@Franz.COM (internet)
> One goal of programming style is to facilitate code changes. In this regard, > the C style weds function and form in a way the Lisp style does not.
The C style was designed to work well with ed, the standard editor, on a teletypewriter. The style of Fortran was similarly inspired by punched cards. The style of Lisp was inspired by full-screen editors with commands to move around in expressions: up, down, forward, backward. This is just one of the large number of benefits of having a delimiter at both the beginning and end of an expression, at all levels of expression. Coming from the C language family, this will take a while to register as a feature, but once you understand, you will regard the idea that the line is the most natural division as incredibly backward, almost retarded. Despite being much older than C, the Lisp family did a large number of things right that the C/Unix folks still have not grasped the significance of. Or maybe it is _because_ it is so much older. ///
> > ;;; Display a list using NTH > > ;;; Lisp style code > > (let ((L (list 'a 'b 5 'symbol -14))) > > (dotimes (i (length L)) > > (print (nth i L))))
> The nice thing about the above code is that the parens are essentially > invisible. You don't worry about them, and you get into the habit of > ignoring them.
As a testament to what Duane said (I still remember vividly learning Lisp) you eventually do not even see the parens (except when you have to). It takes some getting used to but your brain will eventually see the "code" automatically. But you have to be patient and _let_ it happen.
Erik Naggum wrote: > Despite being much older than C, the Lisp family did a large > number of things right that the C/Unix folks still have not grasped the > significance of. Or maybe it is _because_ it is so much older. ///
Actually, it's the other way 'round. Lisp _got_ older because it did a large number of things right! It is the original language that has improved on a large number of its successors. In fifty years, Lisp will still be around.
> > ;;; Display a list using NTH > > ;;; Lisp style code > > (let ((L (list 'a 'b 5 'symbol -14))) > > (dotimes (i (length L)) > > (print (nth i L))))
> The nice thing about the above code is that the parens are essentially > invisible. You don't worry about them, and you get into the habit of > ignoring them.
> > ;;; Same code - C style > > (let
> > (L (list 'a 'b 5 'symbol -14)) > > ) > > (dotimes (i (length L)) > > (print (nth i L)) > > ) > > )
> The major problem with the above code is that it is hard to see the > actual code for all of the parentheses screaming "look at me!". The > parens are definitely not invisible in the above code.
The major problem with it is probably that it's wrong! And that one has not seen it, suggests that is very unreadable. In fact I feel it hurts my eyes...
> Here is a small practice fragment I used > just to fool around:
> ;;; Display a list using NTH > ;;; Lisp style code > (let ((L (list 'a 'b 5 'symbol -14))) > (dotimes (i (length L)) > (print (nth i L))))
When you're a bit more experienced, your eyes will see the above code as:
let L (list 'a 'b 5 'symbol -14) dotimes i (length L) print (nth i L)
You know it's right because of the _indentation_, not because of where the parens match. (The fact that the indentation is right because the parens match is a fortunate/planned accident.)
Now you know where Python got it from. They just took the next step and dropped the parens. :-)
> As a testament to what Duane said (I still remember vividly learning Lisp) > you eventually do not even see the parens (except when you have to). It > takes some getting used to but your brain will eventually see the "code" > automatically. But you have to be patient and _let_ it happen.
This is actually no different than any other language. To what extent do C programmers _see_ its punctuation? Commas, semicolons, braces, parens, brackets, etc, all convey meaning immediately without been obsessed about as such. Getting them right can be a significant hurdle as you struggle with the syntax. Once you stop seeing the & and instead think "address", you have got the hang of it. Perl hackers have mastered this technique. The reason many people who have learned C prefer to continue on the C branch of evolution is that they found the process of learning all that syntax quite _painful_. This is especially true for parentheses in C. You only need them in expressions that cross a fairly high complexity threshold and you can get rid of them by simplifying the expressions. Lisp is chock full of parentheses, with no way to get rid of them -- if you simplify your expressions, you end up with _more_ parentheses. The "syntax = pain" equation in most C programmer's heads translates to a desire to reduce the cost of learning a new language by trying to adapt it to the pain they have already been through. However, once you grok the parentheses in Lisp, they are _not_ painful. In fact, they are so much more liberating and enabling and downright _friendly_ that you would just _love_ to have similar tools available in every other language you use. This is why the "economy of syntax" in C is really a "poverty of syntax" and the perceived verbosity of Lisp translates to a wealth of opportunity. Like so many other things in life, you rarely get _only_ what you optimize for. ///
> > ;;; Display a list using NTH > > ;;; Lisp style code > > (let ((L (list 'a 'b 5 'symbol -14))) > > (dotimes (i (length L)) > > (print (nth i L))))
> When you're a bit more experienced, your eyes will > see the above code as:
> let L (list 'a 'b 5 'symbol -14) > dotimes i (length L) > print (nth i L)
Indeed! It took me forever to read lisp code a few months ago, but my lil' ol' pea brain has adapted and now everything else looks silly. Now I think that using newlines for delimiting phrases is a false economy.
> Now you know where Python got it from. They just took > the next step and dropped the parens. :-)
I hope you mean ;) rather than :).
:)
Actually, having written tens of thousands of lines of Python, I have decided that Guido was in error to use indentation (a la fortran?) to group code. It looks nice when the code is in final, presentable form, but ONLY in the short, neat examples Pythoners use to show how nice it is...
While I know that short functions are preferable, sometimes I can't reasonably avoid more lines in a function than will fit on one screen. In Python, I found I couldn't get the indentation correct near the bottom of the function because there was a lot of nesting. I couldn't easily see (or remember) if I needed to unindent one level or three.
Worse, when editing code and changing the structure, emacs, with no consistent delimiter to determine nesting level, could only guess, and usually guessed wrong. It really slowed down prototyping. In a book or in an email exchange on the subject, Python looks so clean, but getting from blank page to finished code was much more tedious than with a uniformly delimited language like lisp.
I would relegate (sounds harsher than I intend) Python to the status of "way nicer than Perl, but still a wannabe lisp". In every aspect, unfortunately.
Eric
-- US Supreme Court hearing 00-836 GEORGE W. BUSH, Petitioner, v. PALM BEACH COUNTY CANVASSING BOARD
Justice (Scalia?) to Mr. Klock (representing Katherine Harris):
20 and therefore, I guess, whether we win, whether your side, 21 the side you're supporting wins or loses, it doesn't 22 change that, and I guess that's moot, but my question is,
> * "Wade Humeniuk" <humen...@cadvision.com> > > As a testament to what Duane said (I still remember vividly learning Lisp) > > you eventually do not even see the parens (except when you have to). It > > takes some getting used to but your brain will eventually see the "code" > > automatically. But you have to be patient and _let_ it happen.
> This is actually no different than any other language. To what extent do > C programmers _see_ its punctuation? Commas, semicolons, braces, parens, > brackets, etc, all convey meaning immediately without been obsessed about > as such. Getting them right can be a significant hurdle as you struggle > with the syntax. Once you stop seeing the & and instead think "address", > you have got the hang of it. Perl hackers have mastered this technique.
This goes even farther to written language in general. I learned to write some Japanese in my early adult years. At first the characters were just disjoint symbols and I struggled in attempting to read words, let alone sentences. Over time, with practice, I began to "see" words, with meaning, and then began to see sentences. If I had continued I am sure that I would eventually have been fluent in reading phonetic Japanese.
Since this discussion has began I have been looking at my Lisp code trying to fathom how my mind is really working. I find that my attention first moves to the symbols in the code then I (very) quickly bound the groups of symbols into expressions with the parens. Because there are expression delimiters at the end and the beginning of an expression I seem to be able to start "anywhere" within a complex expression and quickly work my way backwards or forwards or even jump around to get the gist of what is going on. This way of looking at "code" also extends into how I seem to write Lisp code. When I start to write a function I usually start with just (defun funcname (some-variables) then jump into the middle of the function and write from the inside out. If I encounter something too difficult to write in place I will just write a higher level expression of what I what to do and either carry on or go and write the higher level expression function. The operative word that seems to be popping up here is "expression". The ability to see an expression, by quickly determining its bounds, and then determine its meaning.
Going back to the original posters comments, by putting parens on seperate lines you reduce the ability to quickly determine the bounds of an expression.
In any programming language there is a point where the model of the programmer meets that of the machine. The level of that interface determines what the two can "discuss." The currency of C and Unix is characters and lines. This is the level at which the programmer and the machine interact and there is a rich set of C tools for this type of interaction, cpp, vi, grep, perl, ad infinitum.
The problem with the C approach is that lines and characters are not good at representing structure. Cpp only replaces one string with another, vi is just a front end to a line editor, grep's operation is intimately tied to a 2D array of characters.
In contrast to this lisp adopts a different level of abstraction by basing everything on s-expressions. This allows for a much more powerful set of tools which understand this structure.
* The macro system can perform arbitrary transformations on this structure and not just substitutions. This is more power than most can comprehend, it certainly makes my head spin.
* I can have a "dialogue" with my editor at a semantically meaningful level of abstraction. Not just lines and characters.
* It is possible to search for objects with _context_ as well as identity. This is embodied in thing like destructuring-bind, code walkers and even XSL.[1]
One of the biggest complaints coming from non-lisp languages is that there are all of these irritating parentheses. That is a concession which is made to be able to express structure. Lisp could be defined entirely in terms of graphs with nary a paren in sight and it would still be lisp. Other languages have made another tradeoff by adopting a "more" human friendly syntax for expressing their structure within the context of a 2D array of characters. They have sacrificed the ability to have a useful dialogue with the computer about the structure of the code. One has to remember that these languages were developed in an environment where interaction was expensive and difficult so I think that it was a good tradeoff.
I for one would go insane writing lisp using a punch card reader, Fortran or Cobol for all their warts would be a much better choice. Similarly, if I was using a teletype or glass-tty I would write in C or a similar language, but for god sakes we are in the 21st century now.
> Why prefer the C style? Well, say I later want to add more forms to > the DOTIMES body. With the Lisp Style I have to analyze what belongs > to what before inserting the form between the 2nd and third closing > parentheses -- Easy to mess up, even in relatively simple code like > this.
Other people have replied and said that you should use a lisp aware editor and that is very important. It goes back to the level of discourse, in C you are communicating characters and lines to the machine vi is totally adequate for this. Lisp and editing lisp is about structure; you need an editor which will allow you to edit and interact the structure of your program.
<Start emacs advocacy>
First In XEmacs[2] I always have the following set:
(setq paren-mode 'sexp)
This makes emacs display the s-expression in a different face. Mine adds a subtle yellow highlight to the background when the parens match and a red one when the don't.[3] Like other posters have mentioned you tend to not see the parens after a while, but I find that that only really works for code which is formatted correctly (my way that is ;-)). The highlighting visually indicates the structure of the code it can be seen as part of the dialogue between you and the editor. The editor understands the structure of your code let it help you.
Whith sexp highlighting and good bindings for backward-sexp, forward-sexp, kill-sexp, and the like any lisp code is easily grokked even that with that nasty C style indenting ;-).
In order to simplify my life I made that annoying windows key on my keyboard into a Super key and put all my lisp stuff under there. There are other key bindings for all of this stuff but I don't have the time to look them up, M-x will tell you what any given function is bound to after executing it anyway so you can track them down in your own emacs.
Here are my bindings:
S-right - forward-sexp S-left - backward-sexp S-up - backward-up-list ;; This jumps back to before the paren which ;; started this list (foo bar baz) ;; to^ from^
S-down - down-list ;; moves just past the next '(' "entering" the list. S-k - kill-sexp S-t - transpose-sexp S-y - yank
The above are generally useful so I have them in the global keymap In just lisp mode I also have [ - insert-parentheses ;; This inserts a () and puts the cursor between them. ] - move-past-close-and-reindent ;; This effectively closes the current sexp started with '[' ;; above. It moves the next closing paren into the correct ;; place and moves the cursor to the next line. I'm ;; thinking of moving this to 'enter'
C-q [ and C-q ] will insert the []'s if I still need them in lisp mode.
> With the 'C style', however, the indentation and parenthesis > placement does the work for me, allowing me to add new forms or > delete existing ones,
Again your editor must help you here. The funny thing is that I do lots of lisp and C programming and am continually frustrated that c-mode does not give me semantically useful editing commands like I have gotten used to with lisp. Lines and characters are not the structure of my program.
> 1 per line, to the DOTIMES body (or to the LET body) without > worrying about parentheses. The same goes for adding new bindings or > removing old ones.
Again with a good editor this is easier in Lisp.
> One goal of programming style is to facilitate code changes. In this > regard, the C style weds function and form in a way the Lisp style > does not.
Here I have to strongly disagree, both with the simple case like you mentioned and harder things. With emacs you can make all of those simple c-like changes easily. Furthermore, larger structural changes are easier in lisp, I am constantly making large scale transformation with a couple of key strokes. These are not possible in C since the syntax is generally not uniform. I find many times that I am adding extra {}'s to my C code just to allow me to treat parts of it like s-expressions.
Sorry for the long rant. I have been scarred from having too many people (and students) complain about how hard lisp is while using *pico*!!!! to edit their programs. Programming is a dialogue between man and machine it has the potential to be very collaborative, but both parties need to speaking on the same level. The level of C is lines of characters while Lisp operates at the higher level of graphs and objects rendered as s-expressions. Choose your tools accordingly.
Have fun,
-Eric
Footnotes: [1] This applies since XML is really just a bad syntax for sexps.
[2] I assume it works in GNU Emacs also but I haven't tried.
[3] This is actually most helpful in C and similar languages where one could have a reasonable chance of typing ( ... ].
>>>>> "Frank" == Frank A Adrian <fadr...@qwest.net> writes:
Frank> Actually, it's the other way 'round. Lisp _got_ older because it did a Frank> large number of things right!
I like the argument, but I am not really sure it says very much. The opposite claim, a language that doesn't do large number of things correctly will not get old, seems hard to defend.
I can think of a number of languages that only seems to have gotten some (perhaps even just a few ?) things right that also seems pretty old (FORTRAN, COBOL, pascal and PL/1 just to name a few).
But undeniably, IMHO, no language has ever gotten as many things right as LISP :-)
On a related note, it seems to me that diversity of programming languages was much larger in the begining of programming, if you compare languages such as FOTRAN, LISP, COBOL and APL.
For the past decade or two, mainstream programming languages seems trapped in the Algol tradition. Are this the effect of teaching trapped within the same tradition, modern programmers being mentally lazy and accept only what seem to improve upon wellknown tradition, or are the Algol clan just better at marketing their products?
------------------------+-------------------------------------------------- --- Christian Lynbech | Ericsson Telebit, Skanderborgvej 232, DK-8260 Viby J Phone: +45 8938 5244 | email: christian.lynb...@ted.ericsson.dk Fax: +45 8938 5101 | web: www.ericsson.com ------------------------+-------------------------------------------------- --- Hit the philistines three times over the head with the Elisp reference manual. - peto...@hal.com (Michael A. Petonic)
In article <tz4r8um30ko....@flatt.cs.colostate.edu>, Eric Dahlman <e...@lossage.org> wrote:
>Other people have replied and said that you should use a lisp aware >editor and that is very important. It goes back to the level of >discourse, in C you are communicating characters and lines to the >machine vi is totally adequate for this. Lisp and editing lisp is >about structure; you need an editor which will allow you to edit and >interact the structure of your program.
><Start emacs advocacy>
You make a good case for having an s-expression-friendly editor but emacs is hardly the only game in town for that. There is no need to include emacs in the price of entry into Lisp programming. A lighter editor like vim (or any other vi) is also very good at navigating s-expressions.
What some Lispers seem to like about emacs is the ability to run Lisp in an emacs window, but that wasn't the advantage you were citing.
> Going back to the original posters comments, by putting parens on seperate > lines you reduce the ability to quickly determine the bounds of an > expression.
Quickly, easily and, most important for me, unambiguously!
> Actually, having written tens of thousands of lines of Python, I have > decided that Guido was in error to use indentation (a la fortran?) to > group code. It looks nice when the code is in final, presentable form, > but ONLY in the short, neat examples Pythoners use to show how nice it > is...
I agree. I tried Python a few years ago and liked it, but not enough to move away from Perl. :-)
Using indentation to convey syntax is a step backwards because it confuses form and meaning.
It's also a problem for more pratical reasons because of editors like vi, which insist in using tabs to indent code. Mixing tabs and spaces is a mess. To make it worse, in most of the Unix shops i worked, programmers will use :set ts=4 or (horrors!) :set ts=3 to change the tab width.
So using indentation works, as long as the source code is in good shape, as long as everybody follows the same conventions for tabs and tab width, as long as it's a world slightly more perfect than the one i've been living in.
With Lisp (and C, and even Perl), if the indentation is good great! If not, you can easily use a tool to fix it, and NO MEANING IS LOST.
Having expressed my personal opinion above, let me add that Python is a fine language and the good people who give so much of their time to implement it as free software deserve nothing but praise.
> It's pretty obvious, by inspection, which position is the right one; > if you get it wrong, it's easy enough to c-u c-b Enter or c-u c-f > Enter to fix it up. --browne > Not if you're using a good text editor. Emacs has commands that hop over > balanced parens, that tell you when parens match, that open up new space > on a fresh line and indent to the right place at the same time. It is > VERY hard to mess up if you're using a competent Lisp-savvy text editor.
--Pitman
There is no text editor of which I am aware in which it is easier to position the cursor to make insertions and deletions in the middle of a line rather than inserting and deleting entire lines.
> we also like to see a reasonable amount of code on a screen and the C > style means we only see about a half to a third as much code per screen
--Pitman
> The notion of wasting that much screen space because I _might_, > _someday_, want to add additional code is what strikes me as nearly > criminal. --browne
There are trade-offs here. I agree the C-style wastes valuable screen space. To some extent this is offset by the advent of 17" and 19" screens allowing for smaller fonts. Of course if you really want to save space, you'll just forget about indentation and linebreaks altogether! Presumably this trade-off is not worth it, even for laconic-minded Lispers. IMHO both of you minimize the advantages of C-style. From 20 odd years of programming I can say it is a virtual certainty that with a project of any moderate size I will be constantly adding and deleting lines from logical subsections of code. For me the ease of these modifications is worth the sacrifice of screen space.
Another advantage to the C-style that I neglected to mention is the ease with which you can comment out lines for debugging purposes. With the Lisp style, at least for those final lines with endless close parentheses, you need to jump through those <c-u c-b Enter or c-u c-f> hoops to do this, and then rejoin the lines when your done.
"Roy Mash" <Roy_M...@ci.sf.ca.us> writes: > > we also like to see a reasonable amount of code on a screen and the C > > style means we only see about a half to a third as much code per screen > --Pitman
> > The notion of wasting that much screen space because I _might_, > > _someday_, want to add additional code is what strikes me as nearly > > criminal. --browne
> There are trade-offs here. I agree the C-style wastes valuable screen space. > To some extent this is offset by the advent of 17" and 19" screens allowing > for smaller fonts. Of course if you really want to save space, you'll just > forget about indentation and linebreaks altogether! Presumably this > trade-off is not worth it, even for laconic-minded Lispers. > IMHO both of you minimize the advantages of C-style. From 20 odd years of > programming I can say it is a virtual certainty that with a project of any > moderate size I will be constantly adding and deleting lines from logical > subsections of code. For me the ease of these modifications is worth the > sacrifice of screen space.
I take it that your 20 years of programming is in C and similar languages. Some people in this newsgroup have more than 20 years experience in Lisp programming, and are quite happy with the "canonical" formatting of Lisp code.
Anyway, you are *not* adding/deleting lines of C code. More likely, you are adding/deleting C statements, which happen to occupy an integral number of lines. Adding/deleting Lisp forms *is* easier than this, as long as your editor is capable.
> Another advantage to the C-style that I neglected to mention is the ease > with which you can comment out lines for debugging purposes. With the Lisp > style, at least for those final lines with endless close parentheses, you > need to jump through those <c-u c-b Enter or c-u c-f> hoops to do this, and > then rejoin the lines when your done.
I use #| / |# or #+nil for this purpose. In fact, if you use #+nil, you can comment out an entire form by inserting text at a single place - in C/C++ you'd have to edit at two places.
"Roy Mash" <Roy_M...@ci.sf.ca.us> writes: > I respond to both Messrs Browne and Pitman here:
> > It's pretty obvious, by inspection, which position is the right one; > > if you get it wrong, it's easy enough to c-u c-b Enter or c-u c-f > > Enter to fix it up. --browne
> > Not if you're using a good text editor. Emacs has commands that hop over > > balanced parens, that tell you when parens match, that open up new space > > on a fresh line and indent to the right place at the same time. It is > > VERY hard to mess up if you're using a competent Lisp-savvy text editor. > --Pitman
> There is no text editor of which I am aware in which it is easier to > position the cursor to make insertions and deletions in the middle > of a line rather than inserting and deleting entire lines.
Heighten your awareness. If you don't use emacs/xemacs, then start. If you do use it, then start asking someone who knows better how to make such insertions and deletions.
I'll not participate in a "how many keystrokes does it take" type of discussion between line orientation and expression orientation. However, my intuition and experience tells me that it is at least as easy to insert and delete expressions as lines, and possibly even easier.
> > we also like to see a reasonable amount of code on a screen and the C > > style means we only see about a half to a third as much code per screen > --Pitman
> > The notion of wasting that much screen space because I _might_, > > _someday_, want to add additional code is what strikes me as nearly > > criminal. --browne
> There are trade-offs here. I agree the C-style wastes valuable screen space. > To some extent this is offset by the advent of 17" and 19" screens allowing > for smaller fonts. Of course if you really want to save space, you'll just > forget about indentation and linebreaks altogether! Presumably this > trade-off is not worth it, even for laconic-minded Lispers.
Why laconic? I don't remember the quote exactly, but I believe Einstein advised us to make things as simple as possible, but no simpler. I think lispers might agree with this philosophy. Thus, removing all linebreaks and whitespace is of course not part of the lisp style. However, the wasted space of the C style is not as simple as possible, and thus subject to screen-space optimization.
> IMHO both of you minimize the advantages of C-style. From 20 odd years of > programming I can say it is a virtual certainty that with a project of any > moderate size I will be constantly adding and deleting lines from logical > subsections of code. For me the ease of these modifications is worth the > sacrifice of screen space.
I can assure you, having come from an Algol-style language background myself, that it should not have take you 20 years to learn how to manipulate lisp expressions! Provided, of course, that you actually _want_ to learn how to do so.
> Another advantage to the C-style that I neglected to mention is the ease > with which you can comment out lines for debugging purposes. With the Lisp > style, at least for those final lines with endless close parentheses, you > need to jump through those <c-u c-b Enter or c-u c-f> hoops to do this, and > then rejoin the lines when your done.
Not true. It is not necessary to touch the parens in order to comment an expression.
I might sometimes add a line break before the frazzle call, in order to keep the same indentation, but the parens at the end need not be disturbed at all.
-- Duane Rettig Franz Inc. http://www.franz.com/ (www) 1995 University Ave Suite 275 Berkeley, CA 94704 Phone: (510) 548-3600; FAX: (510) 548-8253 du...@Franz.COM (internet)
> Another advantage to the C-style that I neglected to mention is the ease > with which you can comment out lines for debugging purposes. With the Lisp > style, at least for those final lines with endless close parentheses, you > need to jump through those <c-u c-b Enter or c-u c-f> hoops to do this, and > then rejoin the lines when your done.
No, you do not. Usually you find the beginning of the exprssion that ends in that soup of parens and do c-m-f to find the other end of it. Since often the start of that expression is the start of the same line, the extra cost to find the right place is one keystroke, plus one more (linefeed) to get to a new line, properly indented. This possibility of occasionally having to do this two keystroke sequence buys you a tight visual display the rest of the time and is well worth it. See example at end of this post.
(defun foo (x) (cond ((zerop x) 1) (t (* x (foo (- x 1) 7)))))
Suppose I want to comment out the (- x 1) starting from the head of the expression.
c-n c-m-f m-b # | m-f | # [8 keystrokes total]
Result:
(defun foo (x) (cond ((zerop x) 1) (t (* x (foo (- x 1) #|7|#)))))
I type upwards 70 words a minute. That's about 1 word (5 keystrokes) per second. That means I can touch-type tha above edit in 2 seconds. In C, you can't use expression motion commands so you can only touch-type line replacement, not expression replacment.
What about a more complicated edit in that light? I've written the other kind of factorial with two args and don't like the arg order.
(defun bar (x n) (cond ((zerop x) n) (t (bar (* x n) (- x 1)))))
Fixing this in any infix language is work because you have to point with the mouse. In Emacs lisp-mode I write (starting from cursor at head of defun)
c-e end of line m-b backward word m-t exchange words c-s ( b ESC search for "(b" m-f forward word c-m-f forward lisp expression c-m-t exchange lisp expressions
[10 keystrokes total, pretty sloppy of me]
or
c-e end of line m-b backward word m-t exchange words c-m-e end of definition m-b backward word c-m-u up lisp expression c-m-t exchange lisp expressions
[8 keystrokes--ah, much better]
or
m-3 m-f forward 3 words c-m-t exchange lisp expressions c-m-e end of definition c-r ( ESC search backward for "(" c-m-t exchange lisp expressions
[again 8 keystrokes]
or even if i'm clumsy and plodding
m-f m-f m-f forward word, thrice c-m-t exchange lisp expressions c-n c-n down two lines c-m-f forward lisp expression c-m-t exchange lisp expressions
[again 8 keystrokes, would have been 7 if i'd thought to use m-3 m-f on the first line]
So again, basically the edit takes literally 2 seconds. Result:
(defun bar (n x) (cond ((zerop x) n) (t (bar (* x n) (- x 1)))))
Suppose I want to rewrite that COND as an if starting from the revised form above with cursor at the start of the defun and not assuming a command that does that (which some Emacs variants have):
(defun bar (n x) (cond ((zerop x) n) (t (bar (* x n) (- x 1)))))
c-n down line m-f forward word m-Backspace delete word i f insert "if" c-f forward char c-d delete "(" c-m-f c-m-f forward 2 lisp expressions c-d delete ")" m-f forward word c-m-k kill lisp exprssion forward c-m-u up lisp expression c-m-k kill lisp exprssion forward c-y m-y paste last kill, replace last paste with previous kill tab properly indent current line
[17 keystrokes is 4 seconds]
Note I haven't even talked the value of being able to do this as a keyboard macro. Consider the definition:
Suppose you want to add '(muitos muitas) in an otherwise clause. I also want to upgrade this to use single-quote at the same time, and to use the style of case where you put parens around the case options. Cursor initially at the head of the expression.
c-n c-n down 2 lines c-x ( begin keyboard macro definition m-m move to non-whitespace start of line c-f forward char (over paren) ( insert "(" m-f forward word ) insert ")" m-d delete word forward, including the intervening "(" before it c-f forward char ' insert "'" c-m-f forward lisp expression c-d delete ")" c-n down line c-a start of line (positioned for next macro execution) c-x ) end keyboard macro definition c-9 c-x e do keyboard macro 9 times c-p up line c-m-f forward expression [THIS IS WHAT STARTED THE DISCUSSION] linefeed newline + tab Type an otherwise clause, such as: (otherwise '(muitos muitas))
Ignoring the number of keystrokes in the otherwise clause once you're in place to type it, since that will be the same in all text editors, that's 24 keystrokes or 5 seconds to make this edit correctly. It takes more time to type in the 28 chars in my suggested otherwise clause. Total time, 11 seconds.
That's a pretty substantial edit and I bet vi would have trouble making it quite so fast. Note, too that it accomodated programmatically irregular data like the different indentation of (1) and the extra spaces in the first two clauses, and the different line lengths throughout. Note further that the "cost" of the parens being on the same line was the cost of locating the line plus c-m-f linefeed (two keystrokes, or 1/2 second) in exchange for an extra screen line.
And then there's the value of having a programmable editor so you can teach it (by adding new defuns in the same session or by an init file or library) to do new things on a named command or even single keystroke.
d...@goldshoe.gte.com (Dorai Sitaram) writes: > In article <tz4r8um30ko....@flatt.cs.colostate.edu>, > Eric Dahlman <e...@lossage.org> wrote:
> >Other people have replied and said that you should use a lisp aware > >editor and that is very important. It goes back to the level of > >discourse, in C you are communicating characters and lines to the > >machine vi is totally adequate for this. Lisp and editing lisp is > >about structure; you need an editor which will allow you to edit and > >interact the structure of your program.
> ><Start emacs advocacy>
> You make a good case for having an > s-expression-friendly editor but emacs is hardly the > only game in town for that. There is no need to > include emacs in the price of entry into Lisp > programming. A lighter editor like vim (or any other > vi) is also very good at navigating > s-expressions.
That is true, I am guilty of over generalizing here. As I understand it vim, jed and the like are all capable of similar things. I cannot say exactly what since what I know is only hearsay.
> What some Lispers seem to like about emacs is the > ability to run Lisp in an emacs window, but that > wasn't the advantage you were citing.
I was getting a little long winded so I figured I had best quit when I did. What you say is very true about running lisp in an emacs window, it is very powerful. Many people, myself included, really like the ability to incrementally compile and load changes into the running lisp as we are editing. The avoidance of the whole compile-link-run-debug cycle has given me countless hours of my life back.
However, I would also like to point out that running lisp in an emacs buffer also allows lisp and the running program to participate in the collaborative dialogue I mentioned in my last post. This is where the "emacs way" is a real win when working in an introspective language like lisp. If I change a function I can ask lisp who calls the function and edit those functions also.[1] Lisp can tell me about the arguments to my functions as I edit and help navigate the inheritance graph for my classes. Again the point is that I can interact with the system on a higher semantically meaningful level rather than on the level of strings in files.
Ultimately, all of the features of emacs which I am extolling are available in some form for other tools and other languages to varying degrees. Vim is a great example, I have met people who do basically everything I do in emacs with lisp in vim with python. Choose your poison...
To bring this post back to the original poster's problem, he was trying to shoehorn lisp into a line & string structure since this is what he was familiar with. He did not know how to communicate with his computer about the more powerful s-expression. My meta-point is that if something is overly painful you are doing something wrong. Computer science and the common lisp community in particular is full of really smart (and appropriately lazy) people. They are not martyrs or masochists; none of them would be willing to do something overly painful for long. If you are then you are doing something wrong. Don't just dismiss those around you who do not seem to be suffering as lunatics, they probably just know how to avoid or handle the problem you are having.
-Eric
Footnotes: [1] This requires something like xref which isn't in the ANSI spec but I consider to be part of Lisp anyway. You can get similar results from tags but these lose in cases when the use is not textually visible, for instance if it is hidden inside a macro. To be fair not all xrefs are created equal some have varying abilities to see through macros and the like.
It's apparently possible to learn something every day. That is a _slick_ way of eliminating an s-exp... -- (reverse (concatenate 'string "gro.gultn@" "enworbbc")) http://vip.hex.net/~cbbrowne/linuxdistributions.html From a UK local newspaper, the Horsham Friday-Ad: "Parachute for sale, once used, never opened, small stain."
> I agree. I tried Python a few years ago and liked it, but not enough > to move away from Perl. :-)
> Using indentation to convey syntax is a step backwards because it > confuses form and meaning.
Syntax *is* form (semantics is meaning), and indentation (in Python) doesn't *convey* syntax, it *is* syntax.
> It's also a problem for more pratical reasons because of editors like > vi, which insist in using tabs to indent code.
[snip]
This seems akin to saying that "Parens are a problem for more practial reasons because of editors like MS word which don't have parens balancing."
In other words, I'm not quite sure how "there are tools and practices which don't work well with indentation" even if they are *common* tools and practices, works as a practical argument. Clearly, such practices and tools are the *wrong ones* for working with Python, just as having a non-parens balancing editor (at a minimum) is the *wrong* tool for writing Lisp.
Thanks much for the 'long rant'. I appreciate your man-machine interface commments.
I do want to make clear, however, that I did not intend to compare the benefits of C and Lisp as programming languages. My concern was with programming style (eg placement of closing parentheses), not programming substance.
- Here I have to strongly disagree, both with the simple case like you - mentioned and harder things. With emacs you can make all of those - simple c-like changes easily.
The 'changes' I had in mind -- deleting/inserting/commenting out code -- are common to all programming languages. One style question to ask is: what use of white-space makes these programming tasks easier? I claim that if it is reasonably possible to isolate a syntactic 'chunk' -- ie a stretch of code you could comment out or delete without syntactically breaking the program -- on a single line, then you ought to do so, purely as a development tool.
The only relevant counter-argument I have heard to this so far is that my suggestion takes up more screen space. It surely does -- in both C and Lisp.
So if I became convinced that, as a general rule, that the benefits of saving screen space outweighed the benefits of ease of deleting/inserting/commenting out code then I suppose I should start writing my C code along these lines: for (int i =0; i < x; ++i) { <...> <...> for (int j =0; j < y; ++j) { <...> <...> for (int k =0; k < z; ++k) { <...> <...>}}}
On the other hand, fearing I might be ostracized by other C programmers, I might resist the change on sociological grounds. Just as I find myself now tempted to manage Lisp whitespace the Lisp way -- not because it is the best functional choice, but because, well ... who wants to make other programmers <vomit> <wretch>, or be labelled criminal, or worse?