Xref: utzoo comp.lang.lisp:3644 comp.lang.scheme:1666 Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sdd.hp.com!zaphod.mps.ohio-state.edu!rpi!julius.cs.uiuc.edu!apple!well!jjacobs From: jjacobs@well.sf.ca.us (Jeffrey Jacobs) Newsgroups: comp.lang.lisp,comp.lang.scheme Subject: Re: Virtues of Lisp syntax Message-ID: <20301@well.sf.ca.us> Date: 14 Sep 90 19:06:08 GMT References: <3368@skye.ed.ac.uk> <3407@skye.ed.ac.uk> Organization: Whole Earth 'Lectronic Link, Sausalito, CA Lines: 88 Having watched the LISP Syntax thread for a while, I thought a little history might be in order... Way back in the old days, development in LISP and the underlying philosophy of the language were substantially different. LISP was an interpreted language. Debugging and development was done in interpreted mode; compilation was considered the *last* step in the development process. LISP had two fundamental data types, CONS cells and ATOMs. ATOMs were "indivisible", and included "interned symbols", numbers and strings. (Arrays were added, but were less important to the underlying concept). A key aspect of the language was the "equivalence of data and (source)code", i.e. code consisted of LISP stuctures, which could be manipulated *exactly* like any other LISP structure. Note that this is substantially different from the modern view, where "functions (*not* code) are a data _type_" and not directly modifiable, e.g. even "interpreted" code in most modern implementations gets converted to something other than a CONS based structure. This "equivalence" allowed some very interesting capabilities that are no longer available in modern implementations. Since the interpreter operated on list structures, it was possible to dynamically modify code while in the process of execution. Now, most of us didn't write self-modifying code (although we probably all tried it at least once). But we were able to stop an execution, and make changes to code and continue from the breakpoint without having to recompile or start over. We could issue a break, put a trace point around an expression *within* a defined function, and continue. Or we could fix it, and continue; the "fix" would be propagated even to pending calls. E.g. if you had (DEFUN FOO (X Y) expr1 expr2 ...) and expr1 invoked FOO recursively, you could break the execution, change expr2 (or TRACE it, or BREAK it or...), all of the pending invocations on the stack were affected. (You can't do this with compiled code). It allowed things like structure editors (where you didn't need to worry about messing up parends), DWIM, and other features that have been lost in the pursuit of performance. With this view (and combined with the mathematical purity/simplicity of McCarthy's original concept) LISP syntax not only makes sense, it is virtually mandatory! Of course, it also effectively mandated dynamic scoping. "Local"/lexical scoping really came about as the default for the compiler primarily because most well written LISP code didn't use function arguments as free/special variables, so it was an obvious optimization. However, several years ago, Daryle Lewis confided in me that he had intended that UCI LISP be released with the compiler default set to everything being SPECIAL. Given the historical problems in reconciling local and free variables, and the fact that the vast majority of LISPers who learned the language in the '70s and early '80 learned UCI LISP, I can't help but wonder if what affect this might have had on Common LISP... (FWIW, REDUCE was originally done in UCI LISP way back in the early '70s, and BBN/INTERLISP supported MLISP, an Algol like syntax. Seems to me that RLISP must go back that far as well. Given that structure editors are incredibly ancient, I wonder why the people at Utah didn't use one of those. Oh, and almost nobody ever learned LISP using 1.5... Personally, I think the whole reason LISP machines were created was so that people could run EMACS :-) However, if compilation is the primary development strategy (which it is with CL), then the LISP syntax is not particularly useful. Modern block structured syntax is much easier to read and maintain; it also allows constructs such as type declarations, etc. to be much more readable. Infix notation is indeed much more familiar to most people. Keyword syntax in most languages is much more obvious, readable and certainly less prone to errors and abuse than CL. The elimination of direct interpretation of structures (as read) and the almost total use of text editors does indeed leave LISP syntax a relic from the past. Jeffrey M. Jacobs (co-developer of UCI LISP, 1973) ConsArt Systems Inc, Technology & Management Consulting P.O. Box 3016, Manhattan Beach, CA 90266 voice: (213)376-3802, E-Mail: 76702.456@COMPUSERVE.COM