Thread View: net.lang.lisp
18 messages
18 total messages
Started by Jeffrey Jacobs
Fri, 20 Jun 1986 05:38
Against the Tide of Common LISP
Author: Jeffrey Jacobs
Date: Fri, 20 Jun 1986 05:38
Date: Fri, 20 Jun 1986 05:38
125 lines
7356 bytes
7356 bytes
"Copyright (c) 1986, Jeffrey M. Jacobs, CONSART Systems Inc.,
P.O. Box 3016, Manhattan Beach, CA 90266 (213)376-3802
Bix ID: jeffjacobs, CIS Userid 75076,2603
Reproduction by electronic means is permitted, provided that it is not
for commercial gain, and that this copyright notice remains intact."
The following are from various correspondences and notes on Common LISP:
Since you were brave enough to ask about Common Lisp, sit down for my answer:
I think CL is the WORST thing that could possibly happen to LISP. In fact, I
consider it a language different from "true" LISP. CL has everything in the
world in it, usually in 3 different forms and 4 different flavors, with 6
different options. I think the only thing they left out was FEXPRs...
It is obviously intended to be a "compilable" language, not an interpreted
language. By nature it will be very slow; somebody would have to spend quite a
bit of time and $ to make a "fast" interpreted version (say for a VAX). The
grotesque complexity and plethora of data types presents incredible problems to
the developer; it was several years before Golden Hill had lexical scoping,
and NIL from MIT DOES NOT HAVE A GARBAGE COLLECTOR!!!! It just eventually eats
up it's entire VAX/VMS virtual memory and dies...
Further, there are inconsistencies and flat out errors in the book. So many
things are left vague, poorly defined and "to the developer".
The entire INTERLISP arena is left out of the range of compatability.
As a last shot; most of the fancy Expert Systems (KEE, ART) are implemented in
Common LISP. Once again we hear that LISP is "too slow" for such things, when
a large part of it is the use of Common LISP as opposed to a "faster" form
(i.e. such as with shallow dynamic binding and simpler LAMBDA variables; they
should have left the &aux, etc as macros). Every operation in CL is very
expensive in terms of CPU...
______________________________________________________________
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 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).
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...
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
...Not only does he assume you know a lot about LISP, he assume you know a LOT
about half the other existing implementations to boot.
I am inclined to doubt that it is possible to write a good introductory text on
Common LISP; you d**n near need to understand ALL of it before you can start
to use it. There is nowhere near the basic underlying set of primitives (or
philosophy) to start with, as there is in Real LISP (RL vs CL). You'll notice
that there is almost NO defining of functions using LISP in the Steele book.
Yet one of the best things about Real LISP is the precise definition of a
function!
Even when using Common LISP (NIL), I deliberately use a subset. I'm always
amazed when I pick up the book; I always find something that makes me curse.
Friday I was in a bookstore and saw a new LISP book ("Looking at LISP", I
think, the author's name escapes me). The author uses SETF instead of SETQ,
stating that SETF will eventually replace SETQ and SET (!!). Thinking that
this was an error, 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
reference?
"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...
Care to explain this to a "beginner"? Not to mention that SETF is a
MACRO, by definition, which will always take longer to evaluate.
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...
Then try to introduce them to DEFVAR, which may or may not get
evaluated who knows when! (And which aren't implemented correctly
very often, e.g. Franz Common and Golden Hill).
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!
MEMBER is a perfect example. I complained to David Betz (XLISP) that MEMBER
used EQ instead of EQUAL. I only checked about 4 books and manuals (UCILSP,
INTERLISP, IQLISP and a couple of others). David correctly pointed out that
CL defaults to EQ unless you use the keyword syntax. So years of training,
learning and ingrained habit go out the window. How many bugs
will this introduce. MEMQ wasn't good enough?
MEMBER isn't the only case...
While I'm at it, let me pick on the book itself a little. Even though CL
translates lower case to upper case, every instance of LISP names, code,
examples, etc are in **>> lower <<** case and lighter type. In fact,
everything that is not descriptive text is in lighter or smaller type.
It's VERY difficult to read just from the point of eye strain; instead of
the names and definitions leaping out to embed themselves in your brain,
you have to squint and strain, producing a nice avoidance response.
Not to mention that you can't skim it worth beans.
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?
Jeffrey M. Jacobs <UCILSP>
Re: Against the Tide of Common LISP
Author: Stanley Shebs
Date: Sat, 21 Jun 1986 01:11
Date: Sat, 21 Jun 1986 01:11
335 lines
17420 bytes
17420 bytes
In article <1311@well.UUCP> jjacobs@well.UUCP (Jeffrey Jacobs) writes:
> "Copyright (c) 1986, Jeffrey M. Jacobs, CONSART Systems Inc.,
> P.O. Box 3016, Manhattan Beach, CA 90266 (213)376-3802
> Bix ID: jeffjacobs, CIS Userid 75076,2603
>
> Reproduction by electronic means is permitted, provided that it is not
> for commercial gain, and that this copyright notice remains intact."
I don't why I'm bothering to respond to this uninformed flame, but I've got
a few minutes to kill before running off to the compiler conference...
Besides, somebody might read this and suppose that this Jeff Jacobs
knows what he's talking about, which is rarely the case, based on this
limited sample.
>I think CL is the WORST thing that could possibly happen to LISP. In fact, I
>consider it a language different from "true" LISP.
Well gee, I wonder what is "true" Lisp...
> CL has everything in the
>world in it, usually in 3 different forms and 4 different flavors, with 6
>different options.
Actually, they decided to omit flavors, because no one could agree on
a standard! :-)
> I think the only thing they left out was FEXPRs...
FEXPRs are bad (see Pitman's paper in the 1980 Lisp conference)
>It is obviously intended to be a "compilable" language, not an interpreted
>language. By nature it will be very slow; somebody would have to spend quite a
>bit of time and $ to make a "fast" interpreted version (say for a VAX).
So who cares about making interpreted code fast? By the time I get to caring
about the speed of a program I'm building, it's generally stable enough
that compiling is no big deal. ALL production quality Lisps nowadays are
designed to be "compilable" languages. Can't beat the speed of C programs
by running interpreted, you know...
>The grotesque complexity and plethora of data types
Yeah, Common Lisp has just about as many data types as Fortran...
>it was several years before Golden Hill had lexical scoping,
>and NIL from MIT DOES NOT HAVE A GARBAGE COLLECTOR!!!! It just eventually eats
>up it's entire VAX/VMS virtual memory and dies...
So what do broken implementations have to do with the language standard?
>Further, there are inconsistencies and flat out errors in the book. So many
>things are left vague, poorly defined and "to the developer".
It's hard to imagine that a first version of a language standard will be
perfect. I hear about oddities in the Ada language standard too.
Many of the vaguenesses in the Common Lisp standard are to allow
implementations some freedom to do things in different ways. Would
you like it if the *language* standard said that the architecture will
be tagged, and that positive fixnums range between 0 and 32767, and
that they will have a tag of 42?
>The entire INTERLISP arena is left out of the range of compatability.
Most folks that haven't followed the Common Lisp effort don't realize
how monumental a task it was to get all the Maclispers to agree on a
language standard. There is simply no way to get a Lisp that is both
Maclisp- and Interlisp-compatible.
>Every operation in CL is very expensive in terms of CPU...
Not in clever implementations...
>I forgot to leave out the fact that I do NOT like lexical scoping in LISP;
I LIKE lexical scoping in Lisp - dynamic scoping is for special situations,
like rebinding a global variable for the duration of a function (for
instance, one gets an equivalent effect to Unix redirection by rebinding
*standard-input* or *standard-output* to file streams). There is no
good way to do this if you don't have dynamic scoping. Programs that
rely heavily on dynamic scoping are usually sloppily written and extremely
difficult to analyze - things go on behind your back all the time.
Default dynamic scoping in Lisp is the result of history - in 1958,
programming language semantics was not well understood! In another
20 years, no one will understand why anyone would suggest that default
dynamic scoping was a good thing.
>to allow both dynamic and lexical makes the performance even worse.
This is totally wrong.
>lexical scoping was and should be a compiler OPTIMIZATION, not an inherent
>part of the language semantics.
Great - a program that works interpreted, because it relies on dynamic
scoping and your misnamed variable that happened to have been bound a while
ago, will not work because your officemate that you gave a copy of the
compiled code to doesn't have that same variable bound in *his/her* Lisp!
Changing dynamic to lexical scoping is a massive and dramatic change
in program semantics - I prefer my compiler optimizations to affect speed
and not meaning.
>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...
To put things in perspective, the Zetalisp language (that the Symbolics
people sell like hotcakes for big bucks) is at least an order of magnitude
larger and more complex than Common Lisp, which they consider to be a small
subset for the exchange of programs. All reports have been that the
Symbolics is super-fast for development and for execution... does anyone
want to contradict me?
>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
Neither would I - it's not *supposed* to be an instructional book. Does
anyone tried to learn Ada from the ANSI standard? The Common Lisp standard
is very nice for implementors. I appreciate the explanations and comparisons
to other Lisps and I enjoy the jokes. There are some problems, which is why
there is another version in the works. Almost all of the problems are
extremely technical, and take a long time just to explain to someone not
familiar with the language, let alone to solve... There are also some open
problems with language design involved - like compiling to different machines
within the same programming environment, and support of program-analyzing
programs in a portable manner.
>...Not only does he assume you know a lot about LISP, he assume you know a LOT
>about half the other existing implementations to boot.
A competent implementor should and will know about a bunch of implementations.
*I* didn't have any trouble with the references to other Lisps...
>I am inclined to doubt that it is possible to write a good introductory text on
>Common LISP; you d**n near need to understand ALL of it before you can start
>to use it. There is nowhere near the basic underlying set of primitives (or
>philosophy) to start with, as there is in Real LISP (RL vs CL). You'll notice
>that there is almost NO defining of functions using LISP in the Steele book.
>Yet one of the best things about Real LISP is the precise definition of a
>function!
Finally, a semi-valid point. There has been some effort to define various
subsets, but no consensus has emerged. Any time someone defines a subset,
everybody whose favorite feature has been left out will rant and rave and
insist that it be included. By the time you're done, you've got the whole
language again (spoken from personal experience!).
As for the non-use of Lisp definitions, most such definitions are either
simple and wrong, or complicated and right. The Spice Lisp sources are
in the public domain, and people often look at those for ideas. See the
comment about freedom of implementation above.
>Friday I was in a bookstore and saw a new LISP book ("Looking at LISP", I
>think, the author's name escapes me). The author uses SETF instead of SETQ,
>stating that SETF will eventually replace SETQ and SET (!!).
Reports about the death of SETQ and SET have been exaggerated for
a long time...
> Thinking that
>this was an error, 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
>reference?
Chapters 3 and 5 contain information about scoping and binding rules.
Guy Steele has mercifully not repeated the obvious throughout the book!
To answer your question, (SETF x y) *always* expands into (SETQ x y);
see the top of page 94. SETQ sets the lexical binding if there is one,
otherwise the dynamic binding; see the definition of SETQ on page 91
(where there is a reference to the "usual rules"), and the definition
of "usual rules" in the section on variables, p. 55. I think it would
be impossible to write a language standard that caters to those who
can't read.
>"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, it doesn't seem more consistent to *me*! Should we take a vote?
Should we weight the votes in inverse proportion to the ignorance of
the voter?
>Care to explain this to a "beginner"?
Suppose you want to write a macro that expands into something with
a SETF in it. Now suppose that this macro has an list of variables
that all need to be SETFed. If (SETF) is valid, then the list of
things need only be appended - if an empty list is not valid, then
the macro will have to test for this first and do something else if the
list is empty. Also, in the obvious recursive definition of SETF,
expanding (SETF) into NIL is a nice termination case. Note that this
is all convenience; if you like to suffer while programming, use Pascal.
> Not to mention that SETF is a
>MACRO, by definition, which will always take longer to evaluate.
Bogus! This is only true for *some* interpreters and *never* (so far as
I've seen) for compilers. In fact, many expert Lisp hackers replace
functions with equivalent macros when possible, to save function call overhead
(I don't recommend this practice, most compilers have hooks to opencode user
functions when requested).
>Then try explaining why SET only affects dynamic bindings (a most glaring
>error, in my opinion).
So how in the world are you going to get this to work in a compiler that
compiles lexical references into positions on stack frames?
(let ((var (if (random-predicate) '*realvar1* '*realvar2*)))
(set var 45))
Remember, SET evaluates *both* arguments, so it can't know the variable
name until runtime. Here's another example:
(set (read) 45)
Since (set x y) == (setf (symbol-value x) y), it applies only to the
dynamic binding (read the definition of SYMBOL-VALUE carefully).
> Again, how many years of training, understanding
>and textbooks are suddenly rendered obsolete?
Those folks that managed to pass CS 101 shouldn't have any problem.
> How many books say
>(SETQ X Y) is a convenient form of (SET (QUOTE X) Y)? Probably all
>but two...
I use my Lisp 1.5 manual for historical research only (sorry JMC).
>Then try to introduce them to DEFVAR, which may or may not get
>evaluated who knows when! (And which aren't implemented correctly
>very often, e.g. Franz Common and Golden Hill).
Perhaps you should try a non-broken Common Lisp then...
>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!
So what is Real Lisp anyway? Show the definition so we can flame at it!
>MEMBER is a perfect example. I complained to David Betz (XLISP) that MEMBER
>used EQ instead of EQUAL. I only checked about 4 books and manuals (UCILSP,
>INTERLISP, IQLISP and a couple of others). David correctly pointed out that
>CL defaults to EQ unless you use the keyword syntax. So years of training,
>learning and ingrained habit go out the window. How many bugs
>will this introduce. MEMQ wasn't good enough?
MEMQ is a stupid name.
>MEMBER isn't the only case...
This was a tough problem for the designers. On the one hand, everybody
complains about non-obvious names like CAR and CDR and MEMQ. On the
other hand, the considerably better name MEMBER, which ought to be used
to denote *all* sorts of membership tests, had been grabbed up for EQUAL
tests. I would rather have one obvious function name than MEMBER, MEMQ,
MEMQL, MEMBER-EQUALP, ad nauseam. And I *especially* don't want to
write my own membership tests just because I needed to use some specialized
test function!!
>While I'm at it, let me pick on the book itself a little. Even though CL
>translates lower case to upper case, every instance of LISP names, code,
>examples, etc are in **>> lower <<** case and lighter type. In fact,
>everything that is not descriptive text is in lighter or smaller type.
>It's VERY difficult to read just from the point of eye strain; instead of
>the names and definitions leaping out to embed themselves in your brain,
>you have to squint and strain, producing a nice avoidance response.
>Not to mention that you can't skim it worth beans.
Guy Steele has profusely and publicly apologized for the fonts, even though
it's actually the fault of Digital Press, who couldn't seem to manage
a boldface fixed-width font (the manuals printed at CMU were much better).
>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?
I wish more people would think about the issues of language design before
flaming about somebody else's design!
I have no idea what Jeff Jacobs thinks Real Lisp is, but I do know what
objections people have to Common Lisp. Most of those objections go away
when they start to think about efficiency vs usability, or consistency vs
sanity.
For instance, many people object to the sequence functions, on the grounds
that users could write them themselves. So what users want to try writing
SORT? Probably only those with all kinds of time to waste getting a decent
algorithm, debugging fencepost errors, etc. The smart users will suggest
that it be a library function written in Lisp. Ah, but what should be the
interface be? Two arguments, a sequence and a predicate? One argument, a
sequence, and a global variable *sort-predicate*? How about two global
variables and a 0-argument function (don't laugh, people really do these sorts
of things sometimes). Will the sort be stable or not? Now it's unlikely
that two different sites will define their library SORT function to be
quite the same. So the poor person faced with porting a program must
carry along all the libraries from wherever the program was written.
The even poorer person will have to combine programs from several different
places, each with a different sort routine, and try to prevent each
definition of SORT from stepping on the others. At this point, standardizing
on a sort function should seem like the right thing.
Fortranners and Pascallers and Cers don't worry about this sort of thing,
because they just write sort routines and membership tests over and over
and over again, and wonder why they have to work 10 times as hard to get
their programs as sophisticated as the same ones in Lisp.
Speaking of Fortran, why do people think having complex numbers and
different sizes of floats makes a language large and complex? Perhaps
it's rationals and bignums that make the language too complex?
Personally I'm much happier when (* (/ 1 2) 2) = 1 instead of 0,
and when (+ 2405920349 2452458405) is not 45. There's something to be said
for mathematical sanity, which is why symbolic algebra systems have rationals
and bignums. Maybe character objects are bad, but somehow I can't
excited about trying to remember that 121 actually means 'y' (at least
in ASCII, which is not the only character set in the world).
After all, isn't Abstraction a Good Thing?
I think those who flame about language designs should be forced to
design, implement, and distribute their own language, then listen
while know-nothing second-guessers complain about things they
don't understand to begin with...
>Jeffrey M. Jacobs <UCILSP>
stan shebs
Re: Against the Tide of Common LISP
Author: Jeffrey Jacobs
Date: Sat, 21 Jun 1986 21:02
Date: Sat, 21 Jun 1986 21:02
337 lines
16985 bytes
16985 bytes
In <3827@utah-cs.UUCP>, Stanley Shebs responds to my original article, <1311@well.UUCP> jjacobs@well.UUCP... >I don't why I'm bothering to respond to this uninformed flame, but I've got >a few minutes to kill before running off to the compiler conference... >Besides, somebody might read this and suppose that this Jeff Jacobs >knows what he's talking about, which is rarely the case, based on this >limited sample. >I think those who flame about language designs should be forced to >design, implement, and distribute their own language, then listen >while know-nothing second-guessers complain about things they >don't understand to begin with... I certainly appreciate personal attacks like this; they make things so much livelier :-). To make my ignorance perfectly clear, let me state that I have not only been extensively involved in design and distribution of LISP (and other sytems); my experience started in 1971 with UCI LISP. You can find my name along with the other people who really did the work on the front page of the Meehan book. BTW, James Meehan had nothing to do with the original implementations; all he did was edit the book (mostly just reproducing the manuals; he didn't even do much editing). "The New UCI LISP Manual"... It's a bad idea to jump to conclusions about other people's ignorance based on a limited sample, particularly in this medium. (Ad hominem attacks are also considered bad form). >Well gee, I wonder what is "true" Lisp... Let me use the term "Real LISP" (RL) instead. I am not going to give a definition that will be worth flaming at. The point is that CL makes a _radical_ departure from previous LISP work both in terms of syntax and semantics. As an oversimplified definition; development environment is interpreted with dynamic scoping (lexical scoping is a compiler optimization), no distinction between executed code and data unless specifically compiled (i.e. not incrementally compiled), no required keywords and pre-CL function definitions (such as MEMBER). Examples include MACLISP, INTERLISP, FRANZ and UCI. >> CL has everything in the >>world in it, usually in 3 different forms and 4 different flavors, with 6 >>different options. >Actually, they decided to omit flavors, because no one could agree on >a standard! :-) >> I think the only thing they left out was FEXPRs... My error here; FEXPRs are easily duplicated. What is really left out is MACROs, i.e. access to the actual form. >FEXPRs are bad (see Pitman's paper in the 1980 Lisp conference) How did all that work get done before 1980? If we'd only known we were doing it wrong :-). Because of the above, I won't bother to address the Pittman paper. >>It is obviously intended to be a "compilable" language, not an interpreted >>language. "Compilable" should read "compiled"... >Can't beat the speed of C programs by running interpreted, you know... But you can get one heck of a better development environment running interpreted... >>it was several years before Golden Hill had lexical scoping, >>and NIL from MIT DOES NOT HAVE A GARBAGE COLLECTOR!!!! >So what do broken implementations have to do with the language standard? It's not a matter of "broken", it's a matter of incomplete. How much time, effort and money will it take before a "complete" implementation that doesn't derive from SPICE will appear? >Many of the vaguenesses in the Common Lisp standard are to allow >implementations some freedom to do things in different ways Would >you like it if the *language* standard said that the architecture will >be tagged, and that positive fixnums range between 0 and 32767, and >that they will have a tag of 42? Much of the vagueness will have a direct impact on the user and the portability of code. >Most folks that haven't followed the Common Lisp effort don't realize >how monumental a task it was to get all the Maclispers to agree on a >language standard. There is simply no way to get a Lisp that is both >Maclisp- and Interlisp-compatible. Seems easy enough to me; just put everybody's favorite feature into the language and you can get agreement :-). I do like the casual way Interlisp is just ignored; nothing of any importance has ever been done in Interlisp anyway :-). Being serious, your statement is ridiculous. CL isn't Maclisp compatible either. There is a great range of commonality between Interlisp and Mac-lispish implementations. (We stole from the best for UCI LISP <grin>). But there is also a tremendous rivalry between the 2 camps, and a tremendous financial investment in Interlisp... >>I forgot to leave out the fact that I do NOT like lexical scoping in LISP; >I LIKE lexical scoping in Lisp - dynamic scoping is for special situations, >like rebinding a global variable for the duration of a function (for >instance, one gets an equivalent effect to Unix redirection by rebinding >*standard-input* or *standard-output* to file streams). There is no >good way to do this if you don't have dynamic scoping. Programs that >rely heavily on dynamic scoping are usually sloppily written and extremely >difficult to analyze - things go on behind your back all the time. Thanks for your tutorial, I had NO idea what it was for:-). >Default dynamic scoping in Lisp is the result of history - in 1958, >programming language semantics was not well understood! In another >20 years, no one will understand why anyone would suggest that default >dynamic scoping was a good thing. We are actually fairly close on this issue! I certainly would not design a _new_ language with dynamic scoping as the default. (One of the reasons I state that CL is a NEW language, different from RL). The main reasons I suggest dynamic is preferable in LISP are a) historical, b) LISP is not block structured; the separation of declaring a variable SPECIAL (DEFVAR being recommmend, p 68) from an actual function definition makes it very difficult to debug a function "locally", c) the excessive need to provide compiler declarations makes for some pretty ugly code. Well written LISP code should be almost completely independent of lexical or dynamic scoping considerations. A free variable is obviously special; the only real problem comes in when a variable is bound. >>to allow both dynamic and lexical makes the performance even worse. >This is totally wrong. Say WHAT? It certainly is TRUE in an intepreter; it takes longer to look up a lexical variable than a dynamic variable, and it takes even longer when you have to determine whether the lookup should be lexical or dynamic. Add a little more time to check if it's a CONSTANT or DEFVAR... >To put things in perspective, the Zetalisp language (that the Symbolics >people sell like hotcakes for big bucks) is at least an order of magnitude >larger and more complex than Common Lisp, which they consider to be a small >subset for the exchange of programs. All reports have been that the >Symbolics is super-fast for development and for execution... does anyone >want to contradict me? To put things even more in perspective, Symbolics do not "sell like hotcakes". I don't have the number handy, but I believe the number of units sold is less than 4000. Big bucks is putting it mildly; figure a minimum of $120,000 for a decent, single user system. Zeta-Lisp is bigger, but not in the same way as CL; the "biggness" is in the environment and number of available functions (ala INTERLISP). And it REQUIRES very expensive, very specialized hardware. And nobody runs in CL mode by choice; it slows things down a LOT (and still isn't complete). If you would like to assert that the only way to get a decent CL implementation is to develop a Symbolics class machine for it, I'll be glad to agree :-). But I'm real tired of hearing that LISP "is slow" and requires special hardware ; if you can't work with gp multi-user hardware, maybe you should be doing something else. BTW, I've heard reports that Le-LISP can give Symbolics a run for the money using gp architectures. >Neither would I - it's not *supposed* to be an instructional book. So what is everybody supposed to have learned from? >There are some problems, which is why >there is another version in the works. Almost all of the problems are >extremely technical, and take a long time just to explain to someone not >familiar with the language, let alone to solve... There are also some open problems with language design involved - like compiling to different machines within the same programming environment, and support of program-analyzing programs in a portable manner. No sh*t, Sherlock! You think the flames I've put up are even half? Do you think maybe the drive to make it a "standard" may be just a wee bit premature? >>There is nowhere near the basic underlying set of primitives (or >>philosophy) to start with, as there is in Real LISP (RL vs CL). >Finally, a semi-valid point. There has been some effort to define various >subsets, but no consensus has emerged. Any time someone defines a subset, >everybody whose favorite feature has been left out will rant and rave and >insist that it be included. By the time you're done, you've got the whole >language again (spoken from personal experience!). The point isn't the lack of a subset, it the lack of a starting set. RLs started with a small basic set of types and functions. Even though they grew to tremendous size, the growth was mostly by adding new functions. CL starts out with a tremendous base language, attempting to have everything in it. The user pays the price for this... This also goes along with my earlier explanation about how agreement was reached among the LISP community. You have my sympathies. It was a lot easier in my in the "good ol" days... >As for the non-use of Lisp definitions, most such definitions are either >simple and wrong, or complicated and right. That is almost slanderous; do you really want to stand there and say that about all the other LISP manuals around? I find it a lot easier to understand a well defined function than prose. I always find that I get scr**ed by the sentence I didn't read. Good readers tend to skim. >Chapters 3 and 5 contain information about scoping and binding rules. >Guy Steele has mercifully not repeated the obvious throughout the book! >To answer your question, (SETF x y) *always* expands into (SETQ x y); >see the top of page 94. SETQ sets the lexical binding if there is one, >otherwise the dynamic binding; see the definition of SETQ on page 91 >(where there is a reference to the "usual rules"), and the definition >of "usual rules" in the section on variables, p. 55. I think it would >be impossible to write a language standard that caters to those who >can't read. Thanks for the references. Too bad there aren't any in the book.... Unfortunately this isn't written in the proper style of a standard, and I don't think I should have to read 5 pages to find what should be clearly and simply stated under the function definition. Take a look at IEEE and ANSI standards to see what a "real" standard should look like. If I look up SETF, I should be able to find out what it does, not have to read back to the chapter preface. As you so clearly point out, it's a lousy reference manual to boot! >>Then try explaining why SET only affects dynamic bindings (a most glaring >>error, in my opinion). >So how in the world are you going to get this to work in a compiler that >compiles lexical references into positions on stack frames? That's the implementor's problem <grin>. It can be done (but probably isn't worth it). See below for how this should have been handled. >> How many books say >>(SETQ X Y) is a convenient form of (SET (QUOTE X) Y)? Probably all >>but two... I will agree that the _definition_ of SET given is definitely useful; what I object to is the capricious changing of the semantics of a function that is so old and so ingrained in RL. It SHOULD HAVE BEEN GIVEN A NEW NAME!!!!!!! (And this applies to every other function whose historical RL definition has been incompatibly changed). CL is supposed to promote compabitility etc.; the first thing it does is become incompatible with most other LISPs. >I use my Lisp 1.5 manual for historical research only (sorry JMC). Maybe you should do a little more historical research! Or at least read something besides Steele and Winston&Horn v2. >> Again, how many years of training, understanding and textbooks are rendered obsolete? >Those folks that managed to pass CS 101 shouldn't have any problem. Passed CS 101 at what school? What year? Using what implementation of LISP? If you spend 10 years using SETQ thing it's the same as (SET (QUOTE)... or MEMBER is different from MEMQ, and suddenly it all changes, you're gonna be damned unhappy. Especially if you have trained other people and your company's business depends on getting debugged software out the door. (Or, in my case, you often make a living debugging other people's code). >MEMQ is a stupid name. So is SHEBS, (the best I can do for an ad hominem argument :-) . But it's obviously distinct from MEMBER, and has a great deal of "historical" weight behind it... >>MEMBER isn't the only case... >This was a tough problem for the designers. On the one hand, everybody >complains about non-obvious names like CAR and CDR and MEMQ. On the >other hand, the considerably better name MEMBER, which ought to be used >to denote *all* sorts of membership tests, had been grabbed up for EQUAL >tests. I would rather have one obvious function name than MEMBER, MEMQ, >MEMQL, MEMBER-EQUALP, ad nauseam. And I *especially* don't want to >write my own membership tests just because I needed to use some specialized >test function!! Fine. I don't agree, but DON'T CALL IT MEMBER!! Call it something else and if you want to add funky syntax and make it a special form, be my guest. But don't kill my working code that goes back many years!!!! And don't invalidate all of the text books, articles, etc that have already been written and used for many years! >I think those who flame about language designs should be forced to >design, implement, and distribute their own language, then listen >while know-nothing second-guessers complain about things they >don't understand to begin with... Terribly sorry I wasn't available to help with the CL definition. On the other hand, perhaps a little more time should have been taken, and some people who weren't completely devoted to a life of developing LISP per se should also have been consulted. Let's face it; design by committee is a polite term. The kitchen sink approach is probably more apt. As you and I point out, one of the key means of getting agreement was including everybody's favorite feature! This ain't "design"... There are a lot of good things in CL, but it's a mammoth compromise and you and I both know it. There are tons of problems and the mad rush to make it a standard is very premature. It's the rush to make it a standard that I object to. It is simply not a good standard. As you say: >Perhaps you should try a non-broken Common Lisp then... >Not in clever implementations... Where are these clever, non-broken Common LISPs? As I also point out, implementation is very costly and the results are forcing many firms to recreate LISP in C to get decent performance for their ES shells. The only "non-broken" versions I am aware of are re-written SPICE! It's hard to believe that MIT can't come up with a version (or if they have, they haven't notified me of the update; last version I have is 0.286). Perhaps you can keep the personal attacks to a minimum next time. You may not know who I am; that doesn't make me an illiterate idiot! I've probably been around a LOT longer than you have, and probably have a much wider range of experience, which is not confined to LISP language development (although we have more LISP designs than you'll ever see). -JJ, CONSART Systems Inc. CIS: 75076,2603 BIX: jeffjacobs
Re: Against the Tide of Common LISP
Author: Charles Hedrick
Date: Sat, 21 Jun 1986 21:09
Date: Sat, 21 Jun 1986 21:09
77 lines
5404 bytes
5404 bytes
In general, I agree with Shebs' response. A couple more things: It was realized when CL was designed that it was larger and would take more time to implement correctly than Lisp 1.6. The designers took the view that this was a one-time price, and that it was better for each manufacturer to spend a few more man-hours once if it would save their users from then on. This is probably right. There is nothing in CL that makes a fast interpreter impossible. There is plenty that makes it difficult. The DEC-20 implementation has an interpreter that is reasonably fast. The major speed problem is caused by lexical bindings. Simple implementations are low because they have to put all of the bindings on lists, thus replacing push by CONS and pop by a GC. The DEC-20 implementation prevents this by putting the data on the stack where possible, and copying into the heap in the rare case of someone asking for an actual closure object. There are similar tricks for the other difficulties. The resulting interpreter is not as fast as an interpreter for Lisp 1.6, but the difference is not enough to cause trouble. What we get for all of this pain is an interpreter whose binding semantics are compatible with those of the compiler. I spent several years supporing UCI Lisp. Many users never compiled code because when they compiled it, it stopped working. The primary problem was that the binding semantics changed, and they suddenly had to declare lots of things "special". In my opinion it is worth a man-month from each implementor to get rid of this problem. Actually, I voted against this feature of CL. I would have preferred that the compiler use "special" all the time. (We did this to a compiler for a variant of UCI Lisp. It helped things immensely.) It was turned down, I think for two reasons (1) This makes the compiler pay in efficiency. Adding lexicals to the interpreter makes the interpreter pay in efficiency. Since you compile when you want speed, it makes sense to pick the definition that is fastest for the compiler (2) There are a number of people who believe that lexical binding is safer, and who want to use lexical closures. A number of things said in the original posting are just wrong. I can think of no way to implement SET so it works for lexically-bound variables in compiled code. There are such things in UCI Lisp. They are called SPECIAL. I am reasonably sure that SET does not work with them. If the manual fails to say this, it is a documentation error. The primary reason for SETF is for convenience in writing code that writes other code. Examples are macros and code to implement flavors or other structured-programming constructs. For all such purposes, it is very handy to be able to reverse the definition of a component. That is, suppose we have a list, and we refer to its components as (CAR X), (CADR X), and (CADDR X). We want to be able to change the components uniformly by doing (SETF (CADR X) ...) instead of having to transform this into (RPLACD (CAR X) ...) If a person is writing the code, this may not be so important (though it is a very common bug for a person to write (RPLACA (CDR X) where he meant (RPLACD (CAR X)). However researchers are now beginning to depend upon high-level tools. We want a macro or other code-constructor to be able to take the definition of a component and be able to build code to change the element by sticking SETF around it. It is precisly such large systems as KEE that make many of the complexities of CL necessary. Personally I would have wished for CL to be smaller. As the manager of a number of timesharing systems, I cringe at a Lisp where each user takes 8 MB of swap space. (Our DEC-20 implementation does better than this. We were very careful to allow as much to be shared as possible. The implementation that takes 8MB per user was designed primarily for single-user workstations. Unfortunately we have a situation where we want 4 people to use it.) But I have no question that the things that made it bigger will save a number of people time, and facilitate the building of large systems. My sense of things is that CL implementations, particularly after they have been in use of a few years and get tuned, will be about as fast as other Lisps. However they will be enormous. The attitude of the CL designers was "memory is cheap". If you envision CL as being used for large systems on single-user systems, this is right. That's certainly what the CL designers had in mind. Those of us trying to run large student timesharing systems may have some problems with this. It may be that for us a subset will prove helpful. Or the vendors that supply timesharing systems may simply be more careful in their implementations, so that all of the code can be shared.
Re: Against the Tide of Common LISP
Author: Jim Kempf
Date: Mon, 23 Jun 1986 15:03
Date: Mon, 23 Jun 1986 15:03
5 lines
876 bytes
876 bytes
What really upset me about CLtL is that the quality of the book binding was so bad. I have had my book for about a year and a half, use it constantly, and it has already fallen apart. I hope DEC chooses a better book binding technology when they issue the next edition. Jim Kempf hplabs!kempf
macros vs. functions (was: Against the Tide of Common LISP)
Author: michael maxwell
Date: Mon, 23 Jun 1986 18:36
Date: Mon, 23 Jun 1986 18:36
19 lines
1692 bytes
1692 bytes
In article <3827@utah-cs.UUCP> shebs@utah-cs.UUCP (Stanley Shebs) writes: >In article <1311@well.UUCP> jjacobs@well.UUCP (Jeffrey Jacobs) writes: >[...] In fact, many expert Lisp hackers replace >functions with equivalent macros when possible, to save function call overhead >(I don't recommend this practice, most compilers have hooks to opencode user >functions when requested). My question doesn't really have anything to do with the original posting(s), rather I'm interested in this comment on macros vs. functions. Many of the functions I write are only called from one place in the program (not recursively!), and are never called by the user; they're just conveniences for top-down programming. I've often wondered whether turning them into macros wouldn't speed things up. Anyone care to comment on Stan's contention that turning such functions into macros doesn't speed things up? comment on the -- Mike Maxwell Boeing Artificial Intelligence Center ...uw-beaver!uw-june!bcsaic!michaelm
Re: Against the Tide of Common LISP
Author: martin
Date: Wed, 25 Jun 1986 00:52
Date: Wed, 25 Jun 1986 00:52
115 lines
6686 bytes
6686 bytes
In article <1311@well.UUCP> jjacobs@well.UUCP (Jeffrey Jacobs) writes:
>I think CL is the WORST thing that could possibly happen to LISP. In fact, I
>consider it a language different from "true" LISP.
To me, CL is the first "true" Lisp I have seen! Functions are 1'st class
objects, built-in functions have names that describes what they do, not
idiotic short-hands like Maclisp's munkam or Franz' dtpr, it has the nicest
set of data types I have seen (though I admit that it is more an feature
than an important part of the language) and powerful arithmetic.
>...
>different options. I think the only thing they left out was FEXPRs...
You don't want FEXPRs. Use macros.
>It is obviously intended to be a "compilable" language, not an interpreted
>language. By nature it will be very slow; somebody would have to spend quite a
>bit of time and $ to make a "fast" interpreted version (say for a VAX). ...
Why should anyone spend time and money to make a fast interpreter? It is the
compiled code that should be "fast".
>and NIL from MIT DOES NOT HAVE A GARBAGE COLLECTOR!!!! It just eventually eats
>up it's entire VAX/VMS virtual memory and dies...
>
Neither have Zetalisp on the Lambda... What's that got to do with the language
definition?
>The entire INTERLISP arena is left out of the range of compatability.
Yes, fortunately!
>As a last shot; most of the fancy Expert Systems (KEE, ART) are implemented in
>Common LISP. Once again we hear that LISP is "too slow" for such things, when
>a large part of it is the use of Common LISP as opposed to a "faster" form
>(i.e. such as with shallow dynamic binding and simpler LAMBDA variables; they
>should have left the &aux, etc as macros). Every operation in CL is very
>expensive in terms of CPU...
If so, it is time to build new machines that supports the language better.
For years now we have built the machines and then designed the languages for
them when it should be the other way around. That's why we are stuck with
ugly things like F-N, Pascal and C. (No flames plz, I've heard them before.)
>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 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).
That is perhaps a matter of tast but I do like lexical scoping. I have
tested/debugged a lot of "other peoples" Maclisp and Franzlisp code which is
heavily built on dynamic scope (which is a type of side effect to me) and
*that* can drive you crazy.
Besides, when do you get dynamic scope without asking for it? The only
(few) cases I could find is when it is "natural" (in some way),
ex. with-open-file.
Lexical scoping *IS* a part of the language semantics! Lexical scoping as
a compiler optimization seems utterly stupid to me.
>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
>
>...Not only does he assume you know a lot about LISP, he assume you know a LOT
>about half the other existing implementations to boot.
>
It is simply not a tutorial book. It is a book for Lisp hackers/implementors/
developers.
>Friday I was in a bookstore and saw a new LISP book ("Looking at LISP", I
>think, the author's name escapes me). The author uses SETF instead of SETQ,
>stating that SETF will eventually replace SETQ and SET (!!). Thinking that
^^^^^^^^^^^^^^^^^^^^
>this was an error, I checked in Steel; lo and behold, tis true (sort of).
It is an error. SETF will (eventually) replace SETQ. It can not replace SET.
>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
>reference?
At the moment of reference you can only see one binding of a variable. Which
one depends of the circumstances and follows the rules outlined in chapter 3.
I have never had any trouble with this, it is very simple.
>"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...
>
>Care to explain this to a "beginner"? Not to mention that SETF is a
>MACRO, by definition, which will always take longer to evaluate.
>
All functions and special forms that allow a infinite number of arguments
should allow zero args if possible, for consistency. Care to explain to a
"beginner" why a function that allows one, two, three or X (pair of)
arguments should not allow zero arguments?
Macros do NOT always take longer to evaluate. It may be true interpreted
but never compiled.
>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? ...
It is obvious. If SET affects lexical bindings a function may not always
return the same thing depending on the names of its (lexical) variables.
Suppose SET did change lexical bindings and you have this (silly) function :
(defun foo (a b) (set a b))
Now, if you have a variable 'x' dynamicaly bound to 42 then the call
(foo 'x 666)
would, of course, change the dynamic binding of 'x' to 666. But if your
dynamic variable happen to be called 'a' the call
(foo 'a 666)
would NOT change the dynamic binding of 'a' which is probably not what
you expected...
PEM
--
Per-Erik Martin, Computing Science Dep., Uppsala University, Sweden
UUCP: martin@kuling.UUCP (...!{seismo,mcvax}!enea!kuling!martin)
Re: Against the Tide of Common LISP
Author: Jeffrey Jacobs
Date: Wed, 25 Jun 1986 14:54
Date: Wed, 25 Jun 1986 14:54
211 lines
11243 bytes
11243 bytes
>References:<5194@topaz.RUTGERS.EDU <1311@well.UUCP> <3827@utah-cs.UUCP> In <5194@topaz.RUTGERS.EDU>, Charles Hedrick says: >In general, I agree with Shebs' response. A couple more things: Mr. Hedrick does not state what points he agrees with. However, he then goes on to say: >There is nothing in CL that makes a fast interpreter impossible. >There is plenty that makes it difficult. The DEC-20 implementation >has an interpreter that is reasonably fast. The major speed problem >is caused by lexical bindings... I fail to see where Hedrick disagrees with me, unless it's my use of the word "impossible". Since the original article was deliberately "flameboyant" I'll be glad to downgrade "impossible" to "plenty difficult" <grin>. >Personally I would have wished for CL to be smaller. As the manager >of a number of timesharing systems, I cringe at a Lisp where each user >takes 8 MB of swap space. This also sounds suspiciously like agreement with my position about CL being a bit overgrown. Just how many UCI LISP versus CL users can a 2060 support? >Simple implementations are slow because >they have to put all of the bindings on lists, thus replacing push by >CONS and pop by a GC. (Note: Hedrick's original msg. had "low", not "slow"). The overhead penalty is not in the CONSing; the time for CONS should be roughly equal to pushing the data on the stack. The REAL overhead is in accessing the data, whether searching a list or searching a stack. If the value of FOO is accessed many times, the overhead increases dramatically. In fairness, should be pointed out that there is possibly BETTER performance in a lexically scoped interpreter using a stack than in a deep bound dynamic environment, as the interpreter would go the value cell if it wasn't found in the lexical environment, as opposed to searching the entire stack. In the case of using a list for the environment, a careful implementation should be able to RETURN the "lexical" environment to the free list on exit, reducing the need for GC. (I assume that he didn't do a GC after every function exit). >What we get for all of >this pain is an interpreter whose binding semantics are compatible >with those of the compiler. I spent several years supporing UCI Lisp. >Many users never compiled code because when they compiled it, it >stopped working. The primary problem was that the binding semantics >changed, and they suddenly had to declare lots of things "special". <flame on> The code didn't "stop working"; the programmer just didn't know how to do a complete job. It's a matter of not being taught decent programming habits. Versions of DWIM/Programmer's Assistant have been available for UCI LISP since 1972, which make it very easy to keep track of necessary SPECIALs, etc. The notion that gets into student's heads that they can just blindly write code without any forethought or planning is what gives Comp. Sci. grads such a bad reputation in industry. There's really no excuse for failing to understand such a basic principle of the language being used. Some people need to be protected from themselves; LISP (and assembler) are not for them. Let them use PASCAL and M-2. <flame off> Historically, the default to local/lexical compilation was an obvious optimization, based in large part on the fact that most good LISP programmers wrote very functional code with very little need of dynamic scoping. >In my opinion it is worth a man-month from each implementor to get rid >of this problem. A man-month? See below... > Actually, I voted against this feature of CL. I > would have preferred that the compiler use "special" all the time. >(We did this to a compiler for a variant of UCI Lisp. It helped >things immensely.) You're gonna hate me for this; UCI LISP was meant to be that way when released. Daryle had planned to do it, but didn't have time and forgot to tell me before he graduated. I was so busy with the interpreter and other things that as long as nobody reported bugs, I didn't give the compiler much thought. So it just fell through the cracks <sigh>. (I'm not sure we could have convinced Rusty, anyway). Development at UCI basically stopped when I left <sigh>. If you voted against it, it sounds like we agree! >It was turned down, I think for two reasons (1) >This makes the compiler pay in efficiency. Adding lexicals to the >interpreter makes the interpreter pay in efficiency. Since you >compile when you want speed, it makes sense to pick the definition >that is fastest for the compiler This is highly machine and implementation dependent. There are 2 things that must be considered, time to perform the binding and time to access. Time to access is really the key to performance. (Given the overhead involved in CL's extended binding capabilities, time to bind might even be cheaper <grin>). >(2) There are a number of people who >believe that lexical binding is safer, and who want to use lexical >closures. From an overall, general language design perspective, I believe that lexical scoping is better. But there should be a SYNTAX to go along with it. LISP syntax simply doesn't provide a decent distinction between lexical and dynamic; I can go along with either one or t'other, but not mixed. Besides, we need at least one language with dynamic scoping <grin>... >A number of things said in the original posting are just wrong. I can >think of no way to implement SET so it works for lexically-bound >variables in compiled code. There are such things in UCI Lisp. They >are called SPECIAL. I am reasonably sure that SET does not work with >them. If the manual fails to say this, it is a documentation error. If you put on your "stupid ways to do it" cap, you could figure out a way to do it. But it's not really something you would WANT to do. SET has ALWAYS been a problem, more so when interpreted than compiled, due to the shadowing problem. For consistency, CL should have thrown out SET, and defined a new function, maybe SET-SYMBOL-VALUE. But is should NOT have changed the semantics of SET (or MEMBER). The definition of SET in CL is very useful; it's the name I object to. BTW, SET should work with variables declared SPECIAL. I'm not sure what your comment means. >The primary reason for SETF is for convenience in writing code that >writes other code. Examples are macros and code to implement flavors >or other structured-programming constructs... >... However researchers are now beginning to depend upon high-level >tools. We want a macro or other code-constructor to be able to take >the definition of a component and be able to build code to change the >element by sticking SETF around it. It is precisly such large systems >as KEE that make many of the complexities of CL necessary. Perhaps this is why KEE is being rewritten in C :-)? (So are most of the other high end shells. Want to bet that the C implementation looks a lot like "Real LISP (RL")? The results of using constructs like SETF (and similar features in ADA) aren't in yet, and won't be for many years. My personal opinion is that they will prove undesireable due to difficulty in debugging them and "type" problems. I think it's better to write a more specific function that's changeable rather than a "generic" function. But SETF as a macro does involve at least one more EVAL (despite what Shebs said). >But I have no question that the things that >made it bigger will save a number of people time, and facilitate the >building of large systems. My sense of things is that CL >implementations, particularly after they have been in use of a few >years and get tuned, will be about as fast as other Lisps. However >they will be enormous. The attitude of the CL designers was "memory >is cheap". If you envision CL as being used for large systems on >single-user systems, this is right. That's certainly what the CL >designers had in mind. Those of us trying to run large student >timesharing systems may have some problems with this. It may be that >for us a subset will prove helpful. Or the vendors that supply >timesharing systems may simply be more careful in their >implementations, so that all of the code can be shared. They also assume the CPU is cheap!!! There's an old saying: "LISP programmers know the VALUE of everything and the COST of nothing". Have you seen the price for memory launched into orbit lately? It's definitely not cheap! how often have we heard about "artificially intelligent" robots exploring Mars (or wherever). Given the power and weight required for CL, you can forget that one!!! In fact, given the current trend, almost no delivered E.S. system will be in LISP. "Rewriting" it in C after "prototyping" seems well on the way to becoming an acceptable part of the process; you can bet that this will not be economically viable in the real world. It might be cheap when you have a University grant or DARPA to support you; it gets a little more complicated when you have to justify a single user station for $125,000 (or even $50,000) to a manager. Then tell him that once you have it working, you'll have to rewrite it! From a business point of view, I can get a lot VAX for my money... I envision LISP being used for a great many things besides "large systems". It's hard to visualize using CL for a small embedded system. As long as I have been in the field, I have heard that LISP was big, slow and hard to learn. I always said that this was a myth, that reasonably sized, efficient LISPs were available. With CL as a standard, I will be flat out wrong. I think CL has it's place; I also think that the choking off of other LISP development is a tremendous mistake. Yet this is exactly what is happening; implementors feel that "have" to achieve full CL status (whatever that really is; even SPICE isn't fully "Steele"). Disclaimer: My articles on Common LISP are about Common LISP as defined in Guy Steele's book. It is specifically NOT about any particular implementation; although I may point out deficiencies and deviations from CL as defined in Steele, I am not attacking any implementation or person (INCLUDING Guy Steele). There is a great deal of work in CL; it's the mad rush to make it a "standard" that I am against. -Jeffrey M. Jacobs, CONSART Systems Inc., Manhattan Beach, CA CIS:[75076,2603] BIX:jeffjacobs
Re: Against the Tide of Common LISP
Author: Erik Martin
Date: Thu, 26 Jun 1986 01:11
Date: Thu, 26 Jun 1986 01:11
32 lines
1978 bytes
1978 bytes
In article <1316@well.UUCP> jjacobs@well.UUCP (Jeffrey Jacobs) writes:
>
>In <3827@utah-cs.UUCP>, Stanley Shebs responds to
>my original article, <1311@well.UUCP> jjacobs@well.UUCP...
>...
>>> I think the only thing they left out was FEXPRs...
>
>My error here; FEXPRs are easily duplicated. What is really left out is
>MACROs, i.e. access to the actual form.
What? MACROs left out? Explain plz.
>It's not a matter of "broken", it's a matter of incomplete. How much time,
>effort and money will it take before a "complete" implementation that doesn't
>derive from SPICE will appear?
>...
>recreate LISP in C to get decent performance for their ES shells. The only
>"non-broken" versions I am aware of are re-written SPICE! It's hard to
>...
What's wrong with an implementation derived from SPICE if it is complete?
The implementation we have (under TOPS-20) is derived from Spice and works
fine. It fast enough an lacks only complex numbers (so far, but I don't miss
them). It's not as fast as Good ol' MacLisp but on the other hand, the
compiler haven't been trimmed in ten years (as a mather of fact, the compiler
is the weakest part of it, so far (again)).
PEM
--
Per-Erik Martin, Computing Science Dep., Uppsala University, Sweden
UUCP: martin@kuling.UUCP (...!{seismo,mcvax}!enea!kuling!martin)
Re: Against the Tide of Common LISP
Author: Hugh Redelmeier
Date: Thu, 26 Jun 1986 14:21
Date: Thu, 26 Jun 1986 14:21
8 lines
1120 bytes
1120 bytes
In article <313@hplabsc.UUCP> kempf@hplabsc.UUCP (Jim Kempf) writes: >What really upset me about CLtL is that the quality of the book binding >was so bad. I have had my book for about a year and a half, use it >constantly, and it has already fallen apart. Sounds like DEC uses dynamic binding (it changes over time). Lexical is *much* more appropriate for Common Lisp. Dynamic binding should be an option (cheaper in paperback).
Re: Against the Tide of Common LISP
Author: preece
Date: Fri, 27 Jun 1986 15:54
Date: Fri, 27 Jun 1986 15:54
89 lines
5082 bytes
5082 bytes
> Jeff Jacobs writes: > As an oversimplified definition; development environment is interpreted > with dynamic scoping (lexical scoping is a compiler optimization), no > distinction between executed code and data unless specifically compiled > (i.e. not incrementally compiled), no required keywords and pre-CL > function definitions (such as MEMBER). Examples include MACLISP, > INTERLISP, FRANZ and UCI. ---------- I have to agree with Hedrick and Shebs and one of the primary philosophies of CL -- the compiled environment and the interpreted environment should behave the same way to the greatest extent possible. The notion of dynamic scoping turning into lexical at compilation is appalling. On the other hand, I'm not completely pleased with the CL approach, either. There are times when scoping doesn't do what those of us coming from the non-Lisp side would expect. ---------- > It's not a matter of "broken", it's a matter of incomplete. How much > time, effort and money will it take before a "complete" implementation > that doesn't derive from SPICE will appear? ---------- Isn't Lucid sui generis? Franz Common claims to be, but I gather you consider it to be broken (I haven't used it). ---------- > Unfortunately this isn't written in the proper style of a standard, > and I don't think I should have to read 5 pages to find what should be > clearly and simply stated under the function definition. ---------- There's plenty of discussion on the CL mailing list about problems with the document, but it's not all that bad. A document specifying the complete details of each function (and therefore repeating tons of material common do other functions doing related things) would have been MUCH bigger. Such a thing would be useful, God knows, but for a first statement of the principles and contents of the language, CLtL is much preferable. A more tutorial approach would not have been as effective either. I agree with your complaint about the fonts used for non-text material. Personally, I would have preferred a non-monospaced font and something denser (thus standing out better). I certainly would NOT have supported use of upper-case, which is fine for occasional emphasis but much less readable. ---------- > If you spend 10 years using SETQ thing it's the same as (SET > (QUOTE)... or MEMBER is different from MEMQ, and suddenly it all > changes, you're gonna be damned unhappy. > Fine. I don't agree, but DON'T CALL IT MEMBER!! Call it something > else and if you want to add funky syntax and make it a special form, be > my guest. But don't kill my working code that goes back many years!!!! > And don't invalidate all of the text books, articles, etc that have > already been written and used for many years! ---------- Well, yes and no. You can't do a derivative language with new features without changing the meaning of some of the existing constructs. It's vital, of course, that you point things out sufficiently clearly that the careful reader (anyone who skims this kind of document gets exactly what she deserves) can take note of what has changed. The book is reasonably careful about giving explicit notice about such functions (which your original posting actually complained about). MEMBER, by the way, does not default to EQ testing, it defaults to EQL testing. It should not be a big deal to make that kind of change in existing code -- just change the name of the function in your existing code and provide a macro supporting your name in terms of the underlying CL primitive (I'm sure that kind of change is second nature to you anyway, given the kind of Lisp background you have). The number one goal of CL was to provide a common base for new Lisp development. It seems to be the case that the world of AI vendors has bought that goal -- everybody seems to be building versions of CL, even Xerox. Nobody would expect the first version of something as big as CL to be definitive, but conforming implementations should be close enough that porting will be much easier than in the past. Experience should indicate the specific areas that need further work in specifying a formal standard (an effort now under way) and moving towards common understanding of the issues that were insufficiently specified in CLtL. -- scott preece gould/csd - urbana uucp: ihnp4!uiucdcs!ccvaxa!preece arpa: preece@gswd-vms
Re: Against the Tide of Common LISP
Author: Stanley Shebs
Date: Sun, 29 Jun 1986 05:15
Date: Sun, 29 Jun 1986 05:15
55 lines
3175 bytes
3175 bytes
In article <1019@isl1.ri.cmu.edu> cycy@isl1.ri.cmu.edu (Christopher Young) writes: >>Fortranners and Pascallers and Cers don't worry about this sort of thing, >>because they just write sort routines and membership tests over and over >>and over again, and wonder why they have to work 10 times as hard to get >>their programs as sophisticated as the same ones in Lisp. > >Obviously, you know much about Common Lisp, and nothing about C (and probably >Fortan or Pascal, but since I haven't used the languages in many years, I won't >comment about them). Either that, or you are a pretty poor C programmer. I started life as a Fortranner about 11 years ago, and worked with large Fortran programs in industry. I've also hacked C quite a bit, including a C compiler - I might still be a lousy C programmer tho, there's no rating system as for chess players... :-) >There are reasons why people have C libraries, after all. Well, non-polymorphic library functions aren't particularly useful. A sort routine that only works on arrays of integers doesn't help me sort some hairy structure with an integer slot in it. My experience with C is that getting any dynamic typing requires some really strange union and pointer hacking that would be better done in assembly language maybe. In fact, much of such code seems to duplicate Lisp innards, although someone not familiar with Lisp implementation might not realize it. If C libraries are so useful, why are they 1 or 2 orders of magnitude smaller than Lisp libraries? >I have not duplicated code. An ambitious assertion - I'd like to look at your code and see if that's *really* true. How do you do the equivalent of a membership test without writing a loop each time? > And there are definitely things >I can do much faster in C than in Lisp Sadly, this is still true; but the number of things has dwindled rapidly in the past few years... >The thing that bothers me the most [about CL] is the limitations of >parameter passing. I forget exactly what the problem was...I think I wanted >to have &optional parameters followed by &key, but I'd had to have a &rest >between them. Most annoying. Oh well. I was told the reason for this, but >as I recall, it didn't seem like a very good reason (and I wasn't alone >in my opinion). Sigh, most people flame about the brain-damage of having &keywords in the *first* place, while others are unhappy about no general destructuring a la 3-Lisp and POP-11. Language designers just don't get no respect... > -- Chris Young. stan shebs
Re: Against the Tide of Common LISP
Author: Stanley Shebs
Date: Sun, 29 Jun 1986 22:30
Date: Sun, 29 Jun 1986 22:30
380 lines
19089 bytes
19089 bytes
In article <1316@well.UUCP> jjacobs@well.UUCP (Jeffrey Jacobs) writes: > >In <3827@utah-cs.UUCP>, Stanley Shebs responds to >my original article, <1311@well.UUCP> jjacobs@well.UUCP... > >>I think those who flame about language designs should be forced to >>design, implement, and distribute their own language, then listen >>while know-nothing second-guessers complain about things they >>don't understand to begin with... > >I certainly appreciate personal attacks like this; they make things so much >livelier :-). To make my ignorance perfectly clear, let me state that I have >not only been extensively involved in design and distribution of LISP (and >other sytems); my experience started in 1971 with UCI LISP. I suppose at this point it's appropriate for me to put on my know-nothing hat and proceed to comment on the design (or lack thereof) of UCI Lisp. There's a manual right here... >Let me use the term "Real LISP" (RL) instead. I am not going to give a >definition that will be worth flaming at. The point is that CL makes a >_radical_ departure from previous LISP work both in terms of syntax >and semantics. As an oversimplified definition; development environment >is interpreted with dynamic scoping (lexical scoping is a compiler >optimization), no distinction between executed code and data unless >specifically compiled (i.e. not incrementally compiled), >no required keywords and pre-CL function definitions (such as MEMBER). >Examples include MACLISP, INTERLISP, FRANZ and UCI. Well in that case, let me substitute the term "Obsolete Lisp". People take a dimmer view of poorly defined semantics nowadays - it's no longer OK for Lisp to be "Fortran with parentheses". >>Can't beat the speed of C programs by running interpreted, you know... > >But you can get one heck of a better development environment running >interpreted... Sure - I use the interpreter too. But WHO CARES about the *performance* of the interpreter!!! >>Many of the vaguenesses in the Common Lisp standard are to allow >>implementations some freedom to do things in different ways > >Much of the vagueness will have a direct impact on the user and the >portability of code. Yeah, like improve portability, at least when programmers adhere to the definition of the language. Are you suggesting the language standard for the interchange of programs should read like the UCI manual and say that 577777Q represents zero? I don't think that non-DEC-20 people would like that part of the specification very much! >Being serious, your statement is ridiculous. CL isn't Maclisp compatible >either. There is a great range of commonality between Interlisp and >Mac-lispish implementations. (We stole from the best for UCI LISP <grin>). Somehow I doubt a UCI Lisp program using the ";" or ";;" functions is going to work very well in Maclisp. Square brackets in UCI Lisp and Franz won't go over real well in PSL, where they denote vectors. UCI Lisp and PSL are the only dialects to define functions with a macro DE, while Maclisp and Franz use defun, and Interlispers do it in several different ways. CL is just as compatible with older dialects as the older dialects are with each other! But once you convert to the standard, you don't have to do it any more... It's very misleading to suggest that there isn't a lot of pain and agony to translate one dialect of "Real Lisp" to another. Tim Finin wrote his Franzlator to convert Interlisp code to Franz, and it had hundreds of conversion rules. Common Lisp has the advantage that a number of experienced Lisp implementors met and argued about most aspects of the language, while some of the features of older dialects look like they were put together by an undergrad that had been dropped on the head as a child. PSL has this function DELATQIP for instance, which does destructive deletions on alists using a key, while UCI Lisp has a function SPEAK which returns the number of CONSes executed (although it is not said whether this count is reset between GCs - a rather glaring screwup). Franz defines (and documents!) operations for beating on allocated number cells directly, so one can globally change 3.1416 to be 2.72 (sort of like the undocumented feature of certain Fortrans). >The main reasons I suggest dynamic is preferable in LISP are a) historical, >b) LISP is not block structured; the separation of declaring a variable >SPECIAL (DEFVAR being recommmend, p 68) from an actual function definition >makes it very difficult to debug a function "locally", >c) the excessive need to provide compiler declarations makes for some pretty >ugly code. Huh? Declaration for what? Local variables? >Well written LISP code should be almost completely independent of lexical or >dynamic scoping considerations. A free variable is obviously special; the >only real problem comes in when a variable is bound. (let ((num 45)) (mapcar #'(lambda (x) (+ x num)) '(3 4 5))) I would prefer num to be lexical and not dynamic, even though it is free within the inner lambda. It's also not desirable for typos to suddenly materialize as specials - it would be a tough debug to find. >>>to allow both dynamic and lexical makes the performance even worse. > >>This is totally wrong. > >Say WHAT? It certainly is TRUE in an intepreter; it takes longer to look up >a lexical variable than a dynamic variable, and it takes even longer when you >have to determine whether the lookup should be lexical or dynamic. Add a >little more time to check if it's a CONSTANT or DEFVAR... Ah, we're talking about the interpreter again. I still don't understand why anyone would think interpreter performance would matter - the overhead is so tremendous already that dynamic/lexical lookups aren't necessarily significant. >I'm real tired of hearing that LISP "is slow" and requires special >hardware ; if you can't work with gp multi-user hardware, maybe you should be >doing something else. I don't use Lisp machines, I expect my (compiled) Common Lisp programs to go faster than equivalent C programs, and I beat on the compiler if they don't go fast enough. >>Neither would I - it's not *supposed* to be an instructional book. > >So what is everybody supposed to have learned from? Rodney Brooks has a book "Programming in Common Lisp", Bob Kessler is working on a book that features objects and Common Lisp, and of course the 2nd edition of Winston & Van Horn's "LISP" uses Common Lisp. >>There are some problems, which is why >>there is another version in the works. Almost all of the problems are >>extremely technical, and take a long time just to explain to someone not >>familiar with the language, let alone to solve... There are also some open >problems with language design involved - like compiling to different machines >within the same programming environment, and support of program-analyzing >programs in a portable manner. > >No sh*t, Sherlock! You think the flames I've put up are even half? These problems certainly aren't solved in UCI Lisp either! >Do you think maybe the drive to make it a "standard" may be just a wee bit >premature? So when is it going to be less premature? When we have 40 mutually incompatible Lisp dialects instead of only 10? >>>There is nowhere near the basic underlying set of primitives (or >>>philosophy) to start with, as there is in Real LISP (RL vs CL). It's definitely an exaggeration to suggest that UCI Lisp has some basic underlying set of primitives that CL doesn't. >>Finally, a semi-valid point. There has been some effort to define various >>subsets, but no consensus has emerged. Any time someone defines a subset, >>everybody whose favorite feature has been left out will rant and rave and >>insist that it be included. By the time you're done, you've got the whole >>language again (spoken from personal experience!). > >The point isn't the lack of a subset, it the lack of a starting set. RLs >started with a small basic set of types and functions. Even though they >grew to tremendous size, the growth was mostly by adding new functions. Interlisp grew by adding magic flags to every property list in sight. >CL starts out with a tremendous base language, attempting to have everything >in it. The user pays the price for this... Tremendousness is in the eye of the beholder. A lot of people want to make Common Lisp even bigger. The other aspect (which I mentioned originally) is that one wants to standardize on user functions, rather end up in a situation where each site has massive and mutually incompatible libraries, which defeats portability. For instance, the UCI Lisp sort function lexorder is quite different from PSL's gsort. UCI Lisp's set intersection function takes any number of arguments, while PSL's only allows 2. The user pays the price, in porting effort. >>As for the non-use of Lisp definitions, most such definitions are either >>simple and wrong, or complicated and right. > >That is almost slanderous; do you really want to stand there and say that >about all the other LISP manuals around? I find it a lot easier to >understand a well defined function than prose. >I always find that I get scr**ed by the sentence I didn't read. Good >readers tend to skim. I was exaggerating perhaps, but it does happen. Definitions in manuals are "wrong" if they differ from the source code, which might have error checks or other argument processing. For instance, the UCI Lisp manual has a definition of EQUAL that doesn't say anything about what happens when comparing arrays, although I might guess that it returns nil. Without a copy of source code, I can't really be sure. Sure, you can explain member and some other list functions by definition, but that's about it. For instance, (push x place) sort of expands into (setf place (cons x place)), except that place will get evaluated twice, so the real macro has to be trickier. UCI Lisp avoids this by only allowing variables as places to push things, which is a nuisance. I also notice that the UCI manual doesn't have definitions for any of the array functions, or string functions, or explode, or many others. >Unfortunately this isn't written in the proper style of a standard, and I >don't think I should have to read 5 pages to find what should be clearly >and simply stated under the function definition. >Take a look at IEEE and ANSI standards to see what a "real" standard should >look like. If I look up SETF, I should be able to >find out what it does, not have to read back to the chapter preface. SETF contains a fine description of what it does. It is clearly unreasonable to expect that the description of SETF should also include documentation on SET, RPLACA, and everything else that it expands into, or tutorial material on the handling of symbols and their values. A "real" standard (there's that word "real" again!), for instance my copy of the Ada standard, has *hundreds* of cross references. You can bet that when Common Lisp becomes an ANSI standard, its document will be just the same. >>>Then try explaining why SET only affects dynamic bindings (a most glaring >>>error, in my opinion). > >>So how in the world are you going to get this to work in a compiler that >>compiles lexical references into positions on stack frames? > >That's the implementor's problem <grin>. It can be done (but probably >isn't worth it). See below for how this should have been handled. Presumably UCI Lisp does it wrong too, since the manual notes (p. 105) that "In compiled functions, SET can be used only on globally bound and SPECIAL variables". Should I assume that this gross difference in the behavior of compiled and interpreted code is another "optimization"? >>Those folks that managed to pass CS 101 shouldn't have any problem > [with different languages] > >Passed CS 101 at what school? What year? Using what implementation of LISP? We try to teach our students enduring principles while encouraging them to be flexible in the minutiae of languages and programs. >If you spend 10 years using SETQ thing it's the same as (SET (QUOTE)... >or MEMBER is different from MEMQ, and suddenly it all changes, you're >gonna be damned unhappy. That's life in Lisp land. Personally, I welcomed most of the changes in Common Lisp, since they were considerable improvements over the bizarrities of other dialects, which I had been annoyed at for a long time. >>MEMQ is a stupid name. > >So is SHEBS, (the best I can do for an ad hominem argument :-) . Maybe you should put a SHEBS function in UCI Lisp then - it takes any amount of arguments and returns a random flame! >But it's obviously distinct from MEMBER, and has a great deal of "historical" >weight behind it... "Historical weight" - spare me! This isn't Fortran or Cobol, whose definitions haven't changed significantly in almost the entire history of computer science! >Fine. I don't agree, but DON'T CALL IT MEMBER!! Call it something else and >if you want to add funky syntax and make it a special form, be my guest. Ah, but if we call it DIFFERENT-MEMBER-WITH-JJ-APPROVED-NAME, then many people will complain because the name is too long, or because it's different from MEMBER, or any number of other reasons. >But don't kill my working code that goes back many years!!!! Nobody's forcing you to use Common Lisp. You're perfectly free to fall into the backwaters of computing. >And don't >invalidate all of the text books, articles, etc that have already been >written and used for many years! Too late, the 1959 LISP Programmers Manual is already invalidated. >Let's face it; design by committee is a polite term. >The kitchen sink approach is probably more apt. As you and I point out, >one of the key means of getting agreement was including everybody's favorite >feature! This ain't "design"... Methinks you're getting rather inconsistent. On the one hand, you accuse CL of being specified by including everybody's favorite feature (presumably from pre-existing Lisps); on the other hand, you say that it's a new language that is incompatible with Lisp. Both of these assertions can be true only if the pre-existing Lisps were fundamentally incompatible. But you've already claimed that they are all "Real Lisp" and basically the same! >There are a lot of good things in CL, but it's a mammoth compromise and you >and I both know it. Suppose the Common Lisp committee had all been dropping acid and decided UCI Lisp was "the Ultimate". Non-UCI-Lispers would have promptly ignored the committee and continued to go their own ways. It is interesting to note that the Lisp community has been converging faster on Common Lisp than the DoD types have been standardizing on Ada, and there has been no official dictum that Common Lisp will be used for projects. There is a lot to be said for compromise when the circumstances demand it. >There are tons of problems UCI Lisp (and Franz and PSL and Interlisp) have megatons of problems then. >>Perhaps you should try a non-broken Common Lisp then... >>Not in clever implementations... > >Where are these clever, non-broken Common LISPs? PCLS isn't bad, although it's a subset. But then it's had only about one person-year put into it. Try VAXLisp or Lucid Common Lisp (which has a hot compiler) or HP Common Lisp or Symbolics Common Lisp or Kyoto Common Lisp. >the results are forcing many firms to >recreate LISP in C to get decent performance for their ES shells. I don't know which companies you might be referring to, but the ES shells I've had occasion to examine have such brain-damaged algorithms no amount of translating to various languages is going to help them. Recall the usual shibboleths about benchmarking and performance analysis... >The only "non-broken" versions I am aware of are re-written SPICE! PCLS has a couple functions stolen from Spice, but it's mostly new code. Symbolics Common Lisp is all their own. HP is careful to emphasize that their Common Lisp is not based on Spice, but that's not necessarily an advantage. Spice is good code. You could do a lot worse, especially if you don't pay attention to the specification. >It's hard to believe that MIT can't come up with a version (or if they have, >they haven't notified me of the update; last version I have is 0.286). MIT isn't some sort of magical place whence optimal correct code appears every so often. There aren't many people there willing to build their own Lisp anymore; they either go with a commercial version or hack Scheme instead (a lot of Common Lisp features derive from Scheme, by the way). >You may not know who I am; that doesn't make me an illiterate idiot! I don't *care* who you are; I just go by your statements. >I've probably been around a LOT longer than you have, Probably true - certainly I can't get into an early 70s Lisp frame of mind without working at it. >and probably have a much wider range of experience, There used to be people with a great deal of experience designing oared galleys, but they weren't very helpful with modern programming languages. >we have more LISP designs than you'll ever see So where are all these great Lisp designs eh? Are any of them implemented? Why don't you subject them to public scrutiny? >-JJ, CONSART Systems Inc. Probably everybody is getting tired of this. There is a particular topic that I would be glad to discuss further, which is the rationale for the various design decisions that went into Common Lisp. Many people have asked about various features good or bad, and when I've gone to look into my historical material, there have been some interesting discoveries. For instance, did you know that an early draft (the "Swiss Cheese Edition") proposed no less than 578 functions to operate on sequences? It was some time before it occurred to anyone that keywords might reduce the number of functions. So far, I've been able to find some pretty solid reasons even for some of the most bizarre Common Lisp features. So if anybody has questions, post or mail me, and I'll try to find out the real story and explain it. stan shebs
Re: macros vs. functions (was: Against the Tide of Common LISP)
Author: Stanley Shebs
Date: Sun, 29 Jun 1986 23:37
Date: Sun, 29 Jun 1986 23:37
131 lines
5754 bytes
5754 bytes
In article <574@bcsaic.UUCP> michaelm@bcsaic.UUCP (michael maxwell) writes:
>In article <3827@utah-cs.UUCP> shebs@utah-cs.UUCP (Stanley Shebs) writes:
>>In article <1311@well.UUCP> jjacobs@well.UUCP (Jeffrey Jacobs) writes:
>>[...] In fact, many expert Lisp hackers replace
>>functions with equivalent macros when possible, to save function call overhead
>>(I don't recommend this practice, most compilers have hooks to opencode user
>>functions when requested).
>
>My question doesn't really have anything to do with the original posting(s),
>rather I'm interested in this comment on macros vs. functions. Many of the
>functions I write are only called from one place in the program (not
>recursively!), and are never called by the user; they're just conveniences
>for top-down programming. I've often wondered whether turning them into macros
>wouldn't speed things up. Anyone care to comment on Stan's contention that
>turning such functions into macros doesn't speed things up?
Well mostly yes and a little no.
Consider the situation which I believe is an example of what you're talking
about:
(defun bar (x y)
(foo x y 0))
(defun foo (a b c)
(print c))
When you compile these, you get bar that consists of code to call foo,
and foo that consists of code to call print.
We can change foo to be defined as a macro:
(defmacro foo (a b c)
`(print ,c))
The first step of the compiler is macro-expansion. Macroexpansion replaces
one piece of source code with another, so the compiler's work reduces to
compiling
(defun bar (x y)
(print 0))
And when the compiler compiles this, bar will just be code to call print.
We've saved a lot! One-half the number of function calls and some argument
shuffling. The whole macro expansion business has gone away completely,
and you don't even need to keep the definition of foo around at runtime
(those among us who are still awake will see a problem).
Now, before you run out to turn all your function calls into macros,
there are a bunch of caveats.
1) This technique cannot be used if an argument to the macro is
referenced twice and has a side effect. If foo is defined:
(defun foo (a b c)
(print c)
(print c))
Then the obvious macro definition is
(defmacro foo (a b c)
`(progn (print ,c) (print ,c)))
But if bar looks like
(defun bar (x y)
(foo x y (incf y)))
then expansions yields
(defun bar (x y)
(progn (print (incf y)) (print (incf y))))
which will increment y twice instead of once! The solution where you
lambda-bind the item that shows up twice, as in
(defmacro foo (a b c)
`(let ((tmp ,c))
(print tmp) (print tmp)))
fixes the bug, but the let expands into a lambda application, which is (you
guessed it) a function call! So you haven't won efficiency-wise.
2) As the first caveat showed by example, getting a macro semantically
right can be tricky. Using macros to gain efficiency is asking for
trouble, especially if the functions that you want to rewrite are
complicated.
3) Use of macros can expand code size, since you are replacing a
function call with the whole body. If this is done often, the increase
may be noticeable. As a real fine point, note that increased
code size might bolix the cache and virtual memory, slowing
things down.
4) Macros in most Lisps (including CL) cannot be APPLYed.
5) The macro expansion process throws away the original body.
In the above example, if I redefine foo, bar will be unaffected.
If foo is a function call, bar will get the new function.
6) In the above example, the compiler is quite likely to compile
these calls as jumps, since they are in tail-recursive position.
It may or may not be the case that you get any advantage from the
macro, or it may be a 1% improvement even if the foo function is
called a lot. The only way to know for sure is to look at your
compiled code and see what's being produced. Even then you have
to have done all the other optimization things, like keeping track
of conses and avoiding linear searches down long lists (member fn
does it for instance). These sorts of things can totally swamp
the cost of function calls.
7) Function protocols vary in expense. PSL's functions are cheap, Franz's
are more expensive, Spice Lisp's are very expensive. There is little
point to optimizing cheap function calls, unless you're doing realtime
in Lisp or some such.
8) Some compiler (PCLS for instance) allow you to declare that
functions will be coded "inline", which is almost identical to
macroexpansion. The compiler can then do the tricky parts of
figuring out the equivalent macro of a function and substitute,
while you can still use it as a function etc.
Common Lisp provides a standardized syntax for declaring this inlining
operation, so it is becoming more prevalent as an option for
Lispers. That's why I don't recommend using macros - it has
to be a Lisp where you can't tell the compiler what to do, and
you have to *know* that you will get a measurable speedup.
>Mike Maxwell
stan shebs
Re: Against the Tide of Common LISP
Author: Jeffrey Jacobs
Date: Wed, 02 Jul 1986 01:57
Date: Wed, 02 Jul 1986 01:57
266 lines
12316 bytes
12316 bytes
s.UUCP> Sender: Reply-To: jjacobs@well.UUCP (Jeffrey Jacobs) Followup-To: Distribution: net Organization: CONSART Systems Inc, Manhattan Beach, CA Keywords: In <3837@utah-cs.UUCP>, Stan Shebs writes: >I suppose at this point it's appropriate for me to put on my know-nothing >hat and proceed to comment on the design (or lack thereof) of UCI Lisp. >There's a manual right here... and goes on to beat on UCI LISP. I don't know why he bothered; nobody suggested it should be a standard, or was without problems. With the necessary changes, it might be a good model for a subset of CL (i.e. range and number of functions, etc). But we already know what happens when a subset is attempted :-) >Are you suggesting the language standard >for the interchange of programs should read like the UCI manual and say that >577777Q represents zero? I don't think that non-DEC-20 people would >like that part of the specification very much! No, I'm not suggesting any such thing. The manual(s) are a description of the language implementation, not a "specification". (And it was originally written for a DEC-10). I do think that _parts_ of the manual provide a good example of how things should be written; much of this is actually from the Stanford 1.6 manual. (I also wish that Meehan had done some _real_ editing on the book; there are still typos from the original 1973 Tech Report)! >>But you can get one heck of a better development environment running >>interpreted... > >Sure - I use the interpreter too. But WHO CARES about the *performance* >of the interpreter!!! I care about the performance of the interpreter; development time costs $ (in the real world). A bad interpreter seriously impacts productivity. The longer I can work in the interpreter, the more I can produce. Let's also not forget that (APPLY foo args), where foo is an arbitrary structure results in interpretation, not compilation. >Yeah, like improve portability, at least when programmers adhere to >the definition of the language. It will be interesting to see just how "portable" things will really be. C is nowhere near as portable as many people claim; I suspect that due to the size and complexity of CL that we will see the same problem, (particularly with so many implementations being "broken"). >Somehow I doubt a UCI Lisp program using the ";" or ";;" functions is going to >work very well in Maclisp. Square brackets in UCI Lisp and Franz won't >go over real well in PSL, where they denote vectors. UCI Lisp and PSL are >the only dialects to define functions with a macro DE, while Maclisp and >Franz use defun, and Interlispers do it in several different ways. Is that UCI, Franz or INTER-LISP's fault? They all came before PSL, so it's really PSL's fault. Maclisp used to use DE (and I'm sure it's still there). Remember, the basic order of creation was MAC->Stanford 1.6->UCI. >CL is just as compatible with older dialects as the older dialects are with >each other! But once you convert to the standard, you don't have to do it >any more... It's very misleading to suggest that there isn't a lot of pain >and agony to translate one dialect of "Real Lisp" to another. Tim Finin >wrote his Franzlator to convert Interlisp code to Franz, and it had hundreds >of conversion rules. Translating between Interlisp and MacLisp derived versions was ALWAYS a pain; between MacLisp types it was much less so. (I did CNNVR in about a week). There used to be a program called TRANSOR that worked pretty well; did it get lost? Or does everybody feel the need to start from scratch... >>The main reasons I suggest dynamic is preferable in LISP are a) historical, >>b) LISP is not block structured; the separation of declaring a variable >>SPECIAL (DEFVAR being recommmend, p 68) from an actual function definition >>makes it very difficult to debug a function "locally", >>c) the excessive need to provide compiler declarations makes for some pretty >>ugly code. > >Huh? Declaration for what? Local variables? No, declarations of SPECIALs. >>Well written LISP code should be almost completely independent of lexical or >>dynamic scoping considerations. A free variable is obviously special; the >>only real problem comes in when a variable is bound. > >(let ((num 45)) > (mapcar #'(lambda (x) (+ x num)) '(3 4 5))) > >I would prefer num to be lexical and not dynamic, even though it is free >within the inner lambda. It's also not desirable for typos to suddenly >materialize as specials - it would be a tough debug to find. The example you give is meaningless. The results are identical for either case.' *PLEASE NOTE* that my gripe with CL is that it allows BOTH dynamic and lexical binding. (DEFUN FOO (X Y Z)... can get you in even WORSE trouble if X, Y or Z has been DEF'ed previously. Dynamic is my *personal* preference; I can live with lexical without much heartburn. Allowing both is crazy. CL should have come up with a different mechanism for dynamic binding (maybe DLAMBDA, DLET and DLET*). >>>>to allow both dynamic and lexical makes the performance even worse. >> >>>This is totally wrong. >> >>Say WHAT? It certainly is TRUE in an intepreter; it takes longer to look up >>a lexical variable than a dynamic variable, and it takes even longer when you >>have to determine whether the lookup should be lexical or dynamic. Add a >>little more time to check if it's a CONSTANT or DEFVAR... > >Ah, we're talking about the interpreter again. I still don't understand why >anyone would think interpreter performance would matter - the overhead >is so tremendous already that dynamic/lexical lookups aren't necessarily >significant. It is VERY significant. Variable reference is certainly the most frequent operation in LISP (CL or RL). HISTORICAL note: it is much easier to build a dynamically scoped compiler. The access time to a special cell is equivalent to a stack based variable. A version of UCI LISP at Rutgers did just that; the original release of UCI would have had this, but it fell through the cracks. The main reasons for the lexical scoping in the compiler was space and speed; dynamic binding required an extra PUSH and space on the stack. Memory was a much more critical resource in those days. (I have already pointed out that it was an obvious optimization based on observed coding practices). I assume that nobody would complain if the compilers had also been dynamic, resulting in identical semantics :-) >I don't use Lisp machines, I expect my (compiled) Common Lisp programs to >go faster than equivalent C programs, and I beat on the compiler if they >don't go fast enough. That's great, but not everybody in the world is going to have a compiler beater handy. (And I would certainly like to see your system). >Tremendousness is in the eye of the beholder. A lot of people want to >make Common Lisp even bigger. No argument here. LISP development is a disease akin to drug addiction or alcoholism; once you start, you can't stop! One of my gripes with CL is that there are too many ways to do the same thing. >>>As for the non-use of Lisp definitions, most such definitions are either >>>simple and wrong, or complicated and right. >>I always find that I get scr**ed by the sentence I didn't read. Good >>readers tend to skim. > >I was exaggerating perhaps, but it does happen. Definitions in manuals >are "wrong" if they differ from the source code, which might have error >checks or other argument processing. For instance, the UCI Lisp manual >has a definition of EQUAL that doesn't say anything about what happens >when comparing arrays, although I might guess that it returns nil. >Without a copy of source code, I can't really be sure. If you read it carefully, you will find that an ARRAY is a SUBR; EQUAL would compare the values. The aren't "wrong" as long as the result is specified by the given definition. Steele's book could be MUCH better... >Maybe you should put a SHEBS function in UCI Lisp then - it takes any >amount of arguments and returns a random flame! "Random" is the key word :-). >Too late, the 1959 LISP Programmers Manual is already invalidated. So are about 100 or so other books. >Suppose the Common Lisp committee had all been dropping acid and decided >UCI Lisp was "the Ultimate". Non-UCI-Lispers would have promptly ignored >the committee and continued to go their own ways. It is interesting to >note that the Lisp community has been converging faster on Common Lisp >than the DoD types have been standardizing on Ada, and there has been no >official dictum that Common Lisp will be used for projects. There is a >lot to be said for compromise when the circumstances demand it. Aha! So the real point is that ANY standard is good, not that CL is a good standard!!! My point is that CL is not a good standard... (However, I have been know to compromise when the circumstances demand it). >>Where are these clever, non-broken Common LISPs? > >PCLS isn't bad, although it's a subset. But then it's had only about >one person-year put into it. Try VAXLisp or Lucid Common Lisp (which >has a hot compiler) or HP Common Lisp or Symbolics Common Lisp or >Kyoto Common Lisp. Lot's of subsets around, aren't there <grin>? Last time I checked, neither HP nor Symbolics were "Steele complete"; there were still things either not meeting the standard or still missing. I haven't had a chance to try the other 2. It is still necessary to stay away from some of the more subtle aspects of the specification (in fact one should probably stay away from them anyway). >>the results are forcing many firms to >>recreate LISP in C to get decent performance for their ES shells. > >I don't know which companies you might be referring to, but the ES >shells I've had occasion to examine have such brain-damaged algorithms >no amount of translating to various languages is going to help them. >Recall the usual shibboleths about benchmarking and performance analysis... Inference, Carnegie Group and Teknowlege to start. KES II and NEXPERT are both written in C. I was apparently wrong about Intellicorp converting KEE to C (although from what I hear they should). >>The only "non-broken" versions I am aware of are re-written SPICE! > >PCLS has a couple functions stolen from Spice, but it's mostly new code. >Symbolics Common Lisp is all their own. HP is careful to emphasize that >their Common Lisp is not based on Spice, but that's not necessarily an >advantage. Spice is good code. You could do a lot worse, especially if >you don't pay attention to the specification. Do you mean the Steele specification? If so, and they don't meet it, aren't they "broken", i.e. non-portable and non-CL? >>we have more LISP designs than you'll ever see > >So where are all these great Lisp designs eh? Are any of them implemented? >Why don't you subject them to public scrutiny? Like I said, Lisp development is a disease, once you get it you can't get rid of it. However, these designs are proprietary, and wouldn't be of much interest to you anyway. Some of the work will be published, but publication isn't a very high priority (remember, I'm in industry, not academia). They are the result of applying years of software engineering experience rather than any great theoretical advance. Mostly practical solutions and a couple of new "laws" on garbage collection. -Jeffrey M. Jacobs, CONSART Systems Inc., Manhattan Beach, CA CIS:[75076,2603] BIX:jeffjacobs
Re: Against the Tide of Common LISP
Author: Stanley Shebs
Date: Wed, 02 Jul 1986 16:03
Date: Wed, 02 Jul 1986 16:03
52 lines
3442 bytes
3442 bytes
In article <1372@well.UUCP> jjacobs@well.UUCP (Jeffrey Jacobs) writes: >>Ah, we're talking about the interpreter again. I still don't understand why >>anyone would think interpreter performance would matter - the overhead >>is so tremendous already that dynamic/lexical lookups aren't necessarily >>significant. > >It is VERY significant. Variable reference is certainly the most frequent >operation in LISP (CL or RL). The most frequent operation in the interpreter is to go through the dispatch loop deciding whether to do variable lookups or macro expansion or function application or hook functions or whatever other feature the implementors decided was handy. Variable lookup may be the most common case, but even lexical lookup is likely to be cheaper than function application. I don't recall seeing any thorough studies of the real costs in an interpreter; although when one gets a 20-to-1 or better speedup using a compiler, it's easy to see why some systems rely on an incremental compiler instead! >That's great, but not everybody in the world is going to have a compiler >beater handy. (And I would certainly like to see your system). The nice thing about compiler beating is that it only needs to be done once, and the optimizations are available forever after. If you want a copy of PCLS, send your USnail address to cruse@utah-20 to get the forms. We also have a paper on PCLS that was unfortunately not accepted for the Lisp conference - it shows the severe hacks our compiler does to transform Common Lisp into efficient PSL. >>Spice is good code. You could do a lot worse, especially if >>you don't pay attention to the specification. > >Do you mean the Steele specification? If so, and they don't meet it, >aren't they "broken", i.e. non-portable and non-CL? Sorry to be confusing. What I meant was that there are a number of subtle aspects of the language that an unwary implementor can get caught by. Such things include error and default handling in the package system, argument list binding and declarations, the user hooks for SETF, and many other things. These things are complex for the implementor so that the language user has an easier time with the language - there's no sillinesses with installing magic properties on symbols, etc. When we left out some of these details in versions of PCLS, you can bet we heard from the users! Spice Lisp is the model implementation. There are a few boners here and there, but it goes to a lot of trouble to get details right. Every Common Lisp implementor should study Spice Lisp code, whether or not s/he actually uses any of it directly. PCLS on the other hand is quick and dirty, and invalid programs will get the most mystifying of error messages, since we go for speed! stan
Re: Against the Tide of Common LISP
Author: Andy Freeman
Date: Thu, 03 Jul 1986 02:40
Date: Thu, 03 Jul 1986 02:40
22 lines
1856 bytes
1856 bytes
(apply foo <args>) should be interpreted iff the function it is in is interpreted or it is typed at top level (or appears at top level in a file that is loaded). The function being called will be interpreted if it hasn't been compiled but what's strange about that? If the function was compiled, then compiled code will be run. Any implementation that can't handle this is wrong. It is possible to do lexical variable reference in interpreted code as fast as deep-binding lookup of dynamic variables. Deep-binding lookup in compiled code isn't much faster than it is in interpreted code. (The exception to this is when it can be shown equivalent to lexical scope. Unfortunately, broken compilers don't bother to prove equivalence, they just change the semantics.) Lexical variable reference is much faster in compiled code than in interpreted code. For those of you who are saying "but shallow-binding is much faster, why would anyone use deep-binding", think about multi-processors, or even multi-tasking. Now name a lisp machine that uses shallow-binding. Shallow-binding only works in a very restricted environment. No one wants to work in that kind of environment anymore. -andy
Re: Against the Tide of Common LISP
Author: Darrel VanBuer
Date: Thu, 03 Jul 1986 14:58
Date: Thu, 03 Jul 1986 14:58
24 lines
1802 bytes
1802 bytes
Summary: Transor still exists
In article <1372@well.UUCP> jjacobs@well.UUCP (Jeffrey Jacobs) writes:
>There used to be a program called TRANSOR that worked pretty well; did it
>get lost? Or does everybody feel the need to start from scratch...
>
TRANSOR still exists in the Interlisp world, though it almost disappeared
because noone had wanted to see why it wouldn't compile in VAX or D versions.
I think there are almost no users.
The worst problem now is that the majority of Interlisp programmers have
only used Interlisp D, so have almost no familiarity with the old teletype
structure editor. Transor translations are specified in terms of those
editor commands. Even Jim Goodwin, the author, would like to see transor
disappear, but the problem is that it's not easy to create a tool with the
power and flexibility provided by Transor + editor.
--
Darrel J. Van Buer, PhD
System Development Corp.
2525 Colorado Ave
Santa Monica, CA 90406
(213)820-4111 x5449
...{allegra,burdvax,cbosgd,hplabs,ihnp4,orstcs,sdcsvax,ucla-cs,akgua}
!sdcrdcf!darrelj
VANBUER@USC-ECL.ARPA
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads