Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!clyde!rutgers!husc6!necntc!adelie!mirror!cca!lmi-angel!rpk From: rpk@lmi-angel.UUCP Newsgroups: comp.lang.lisp Subject: Re: Against the Tide of Common LISP Message-ID: <138@lmi-angel.UUCP> Date: Mon, 9-Feb-87 17:38:13 EST Article-I.D.: lmi-ange.138 Posted: Mon Feb 9 17:38:13 1987 Date-Received: Thu, 12-Feb-87 02:24:12 EST Reply-To: rpk@lmi-angel.UUCP (Bob Krajewski) Organization: LISP Machine, Inc (Cambridge Engineering HQ) Lines: 194 Keywords: Common Lisp, Maclisp, Scheme, scoping, packages Summary: Criticism is off the mark In article <> jjacobs@well.UUCP (Jeffrey Jacobs) writes: > > "Against the Tide of Common LISP" > >Further, there are inconsistencies and flat out errors in the book. So many >things are left vague, poorly defined and "to the developer". This is sadly true, though at least CL has a spec isn't simply a summary of what the first implementation did, unlike Interlisp or Maclisp. >The entire INTERLISP arena is left out of the range of compatability. Most of this can be done with a compatibility package, except for the Interlisp ``feature'' about all arguments being optional. (This can be done on the Lisp Machine with lambda-macros, but that's only for MIT-derived machines.) >I forgot to leave out the fact that I do NOT like lexical scoping in LISP; to >allow both dynamic and lexical makes the performance even worse. To me, >lexical scoping was and should be a compiler OPTIMIZATION, not an inherent >part of the language semantics. I cannot agree with this at all; if somebody can't implement lexical scoping in a efficient manner, they're doing something WRONG. At compile time, no time is spent ``deciding'' whether a variable is lexical or special (it's lexically apparent from the code, right ?). In most cases, lexical variables can go on the stack or in registers, which IS efficient. Special variable references go through symbols, at least in a straightforward implementation. That can be pretty efficient, too. >I can accept SCHEME, where you always know >that it's lexical, but CL could drive you crazy (especially if you were >testing/debugging other people's code). Huh ? Whether or not a variable is lexical can be determined by looking at its lexical context (practically an axiom, eh ?). So if it's being used freely, you can assume it's special. >This whole phenomenon is called "Techno-dazzle"; i.e. look at what a super >duper complex system that will do everything I can build. Who cares if it's >incredibly difficult and costly to build and understand, and that most of the >features will only get used because "they are there", driving up the cpu useage >and making the whole development process more costly... Well, maybe having a function like MAP (takes a result type, maps over ANY combination of sequences) is a pain to implement, but the fact there is quite a bit of baggage in the generic sequence functions shouldn't slow down parts of the system that don't use it. The CORE of Common Lisp, which is lexical scoping, 22 special forms, some data types, and evaluation/declaration rules, is not slow at all. It is not as elegant as Scheme, true, there is certainly a manageable set of primitives. Quite a bit of Common Lisp can be implemented in itself. >BTW, I think the book is poorly written and assume a great deal of knowledge >about LISP and MACLISP in particular. I wouldn't give it to ANYBODY to learn >LISP If you're talking about CLtL (Steele), that's true, but it's not meant to teach [Common] Lisp anyway. [More stuff about trying to learn about Lisp (in general) from CLtL. Sort of like trying to learn English from the Oxford Unabridged Dictionary.] >...The author uses SETF instead of SETQ, >stating that SETF will eventually replace SETQ and SET (!!). This is silly. SETQ is very ingrained in Lisp, though ``theoretically'' it's not needed anymore. The author was drawing a conclusion not based on the way people actually use Lisp. The reason why SETF works on symbols (turning into SETQ) is that macros which are advertised to use ``places'' (expressions that give values and can be written into) don't have to check for the simple case themselves -- it's just the logical way for SETF to work. >Thinking that this was an error, What ? >I checked in Steel; lo and behold, tis true (sort of). >In 2 2/3 pages devoted to SETF, there is >> 1 << line at the very bottom >of page 94! And it isn't even clear; if the variable is lexically bound AND >dynamically bound, which gets changed (or is it BOTH)? Who knows? >Where is the definitive reference? It follows the rules for variable scoping, so it follows the same rules that SETQ and MULTIPLE-VALUE-SETQ do. The reason why this is not made explicit is that the author expects (and rightly so) that if a language feature uses a basic language concept (like setting variables), it will follow the rules described for that concept, which were built up early in the book. In this case, the sections on variables (and scoping) and the page before the one you mentioned, which discussed the generalized variable concept (not the generalized ``symbol naming a particular variable which is stored specially or lexically'' concept). >"For consistency, it is legal to write (SETF)"; (a) in my book, that should be >an error, (b) if it's not an error, why isn't there a definition using the >approprate & keywords? Consistency? Generating an "insufficient args" >error seems more consistent to me... Well, (SETF) does nothing. You probably wouldn't write this, but again, a macro would find it useful. Should (LIST) signal an error too ? >Care to explain this to a "beginner"? Not to mention that SETF is a >MACRO, by definition, which will always take longer to evaluate. Since you're a beginner, by your own admission, why do you think that a form which is a macro call will be noticeably more expensive (in the interpreter, the compiled case can't ever be slower) ? There are ways to optimize macroexpansion, you know. Also, anybody can implement SETF as a special form as long as they hide the fact from the user. >Then try explaining why SET only affects dynamic bindings (a most glaring >error, in my opinion). Again, how many years of training, understanding >and textbooks are suddenly rendered obsolete? How many books say >(SETQ X Y) is a convenient form of (SET (QUOTE X) Y)? Probably all >but two... Once you acknowledge the existence of lexical scoping, then SET only makes sense on special variables, because lexically scoped variables can be stored in ways that (1) don't depend on the symbols that name them (2) aren't accessible dynamically from the callee. SET is a FUNCTION that operates on SYMBOLS, not variables. Much of the problem is due to the fact that many textbooks on Lisp before 1982 or so (as opposed to a Scheme derivative with lexical scoping) assume an all-special variable implementation. This is fast becoming a minority for serious users of Lisp. So (SETQ x value) is equivalent to (SET 'x value) in old Lisps, but even then, you're treading on thin ground. The old Lisp Machine implementation went like this: all variables were special in the interpreter, but in the compiler you had shallow binding and local variables lived in the stack and were not accessible at all via SET or SYMBOL-VALUE (called SYMEVAL in Lisp Machine Lisp). The SAME piece of CODE behaved differently depending on whether it OR its callers OR it callees were interpreted or compiled. I think this is true of Maclisp and maybe of Franz. >I don't think you can get 40% of the points in 4 readings! I'm constantly >amazed at what I find in there, and it's always the opposite of Real LISP! Ah, see, now maybe CL suffers from the Swiss Army Knife syndrome, but by using the word ``Real'' you obviously have a few prejudices of your own. (Oh, by the way, they reversed the arguments to CONS, ha ha...) >MEMBER is a perfect example. I complained to David Betz (XLISP) that MEMBER >used EQ instead of EQUAL. It's actually EQL... >How many bugs will this introduce. It won't introduce bugs into new code written by people who read the manual and understand the interface and semantics of MEMBER. Your (legitimate) obstacle is porting ``traditional Lisp'' code to Common Lisp. The experience at LMI is that you use the package system to apparently redefine functions which have the same names as different Common Lisp functions. It is a familiar technique for me because Lisp Machine Lisp had quite a few name conflicts with Common Lisp: ---------------------------------------- (make-package 'real-lisp) (in-package 'real-lisp) (shadow '(member assoc rassoc delete )) ; etc... (export '(memq member)) ;;; If you're a speed freak, change this to a macro, or hope the compiler ;;; can handle inline functions, or that the implementation can call ;;; functions quickly, or use ZL:DEFSUBST on the Lisp machine... (defun member (x list) (lisp:member x list :test #'equal)) (defun memq (x list) (lisp:member x list :test #'eq)) ---------------------------------------- Now you can move things into the REAL-LISP package. If you're more ambitious you could make REAL-LISP a package that actually had all the right symbols in it itself (as opposed to inheriting them) and exporting them, and then other packages could USE it. >Although it's probably hopeless, I wish more implementors would take a stand >against COMMON LISP; I'm afraid that the challenge of "doing a COMMON LISP" >is more than most would-be implementors can resist. Even I occasionally find >myself thinking "how would I implement that"; fortunately I then ask myself >WHY? Well, the main winning alternative is even further away from your Real Lisp than Common Lisp is: Scheme, or T, which can be pretty much turned in a systems programming language.-- Robert P. Krajewski Internet/MIT: RPK@MC.LCS.MIT.EDU UUCP: ...{cca,harvard,mit-eddie}!lmi-angel!rpk