Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

(describe-differences "Scheme" "Common Lisp")

100 views
Skip to first unread message

David Steuber The Interloper

unread,
Sep 12, 1998, 3:00:00 AM9/12/98
to
Perhaps I should also subscribe to the scheme group. In fact, I think
I will.

Meanwhile, could someone please tell me the differences between Scheme
and Common Lisp? I am interested in syntax, primitive functions (like
cons, car, cdr, etc), philosophical differences, size of interpreter
implementation, that sort of thing.

I keep getting suggestions to consider Scheme for a scripting
language. There must be something to it. Currently, I am biased
towards CL because the reference material I have is CL related and I
don't mind implementing a subset.

Thanks.

P.S. A pointer to an online resource that describes the differences
would be more than satisfactory.


--
David Steuber
http://www.david-steuber.com
To reply by e-mail, replace trashcan with david.

When the long night comes, return to the end of the beginning.
--- Kosh (???? - 2261 AD) Babylon-5

Ray Dillinger

unread,
Sep 13, 1998, 3:00:00 AM9/13/98
to
David Steuber The Interloper wrote:
>
> Perhaps I should also subscribe to the scheme group. In fact, I think
> I will.
>
> Meanwhile, could someone please tell me the differences between Scheme
> and Common Lisp?

Scheme syntax, on the surface, looks just like CL syntax -- fully
parenthesized prefix notation.

Scheme macros are different, because they protect you from
inadvertent variable capture (which can happen in a CL macro
where a variable introduced by the macro has the same name
as a variable in scope where the macro is called).

Scheme has one namespace -- a procedure is just a value that
a variable can take on, the same as any other value.

Scheme uses the same rules to evaluate all the forms in a
combination -- the first position object can be either a
proceure or an expression that returns a procedure as its
result -- makes no difference to scheme.

Scheme does check, if the first element in a combination is a
symbol, to see whether that symbol is a macro keyword (aka a
syntactic keyword) or a variable name; the difference being
that, in an ordinary function call (where the leading symbol
is a variable name) the function and *ALL* of the arguments
will be evaluated - in an UNSPECIFIED order - before the function
is called, whereas in a macro call the order and method of
evaluation dependon on the macro expansion. The unspecified
order is so that compilers are free to try to extract the
maximum parallelism available from the algorithm; however
the compiler is also constrained that it must keep side
effects and interferences between the parallel threads
controlled to the extent that nothing happens unless it
could have happened by evaluating these forms in some
concrete non-intermingled order.

> I am interested in syntax, primitive functions (like
> cons, car, cdr, etc), philosophical differences, size of interpreter
> implementation, that sort of thing.

Primitive functions like CAR, CONS, and CDR work in the same
way you'll be used to in CL, except you'll never be sure which
argument is evaluated first -- of course, if it matters, then
the odds that what you have is not a coding mistake are small.

Scheme has far *fewer* functions and libraries than CL -- the
language has been deliberately kept small by requiring a
unanimous consensus of the standards committee rather than a
majority vote before new features are added. In general,
a thing does not become a part of the language until it is
pretty much agreed both that it is needed and that the proposal
is clearly the best, most elegant, and most consistent way to
do it.

There are a lot of things that there is general agreement that
scheme *needs* -- such as an object system and a module system --
but which have not been added to the language because no one
proposal for them has been clearly "the one right thing to do".

Interpreters are fairly rare in the scheme world -- compilation
has pretty much taken over. But scheme systems tend to be MUCH
smaller than comparable CL systems just because of the smallness
of the language.

> I keep getting suggestions to consider Scheme for a scripting
> language. There must be something to it.

Indeed there is. The way procedures and macros are handled in
scheme makes it considerably easier and/or clearer to implement
other language features, or interpreters and compilers for them,
than in CL (note that this is just what I observe in textbooks;
researchers familiar with both almost always pick scheme to
express such things in rather than CL -- not being a CL user I
can't really draw comparisons from personal experience). Also
there are several implementations of scheme (SIOD because it's
tiny, Guile because that's what it was designed for) which are
particularly well-suited for embedding into another application.
I don't think there are any CL systems which fit under 500
kbytes, but I could be wrong.
ray


are handled

Darius Bacon

unread,
Sep 13, 1998, 3:00:00 AM9/13/98
to
tras...@david-steuber.com (David Steuber "The Interloper") writes:

>P.S. A pointer to an online resource that describes the differences
>would be more than satisfactory.

http://www.well.com/user/djello/scheme-for-lispers.html is a quick
overview of what's needed for a Common Lisp user to understand a
Scheme program.

--
Darius Bacon http://www.well.com/~djello

Erik Naggum

unread,
Sep 13, 1998, 3:00:00 AM9/13/98
to
* tras...@david-steuber.com (David Steuber "The Interloper")

| Meanwhile, could someone please tell me the differences between Scheme
| and Common Lisp? I am interested in syntax, primitive functions (like

| cons, car, cdr, etc), philosophical differences, size of interpreter
| implementation, that sort of thing.

the difference is easily observed to be cultural. you cannot compare
cultures, you can only critique them. the Common Lisp is generally very
welcoming -- proof of that is that all the good ideas in Scheme were
adopted in Common Lisp, but none of the bad ones, which Scheme sadly has
refused to let go of.

| I keep getting suggestions to consider Scheme for a scripting language.
| There must be something to it.

Scheme as a culture is much more combative than Common Lisp. Schemers
fight each other over how unclean they are, and only the purest of pure
are admitted into the language -- only causing much _more_ unclean code
to live in "user space", instead. of course they fight everybody else
with this cleanliness obsession, too: they have this _odd_ need to tell
people to use Scheme instead of Common Lisp and impute to Common Lisp all
of the unhealthy properties of Scheme were it ever to become as big and
supremely useful to as many programmers and uses as Common Lisp is, but
Scheme does _not_ scale well. Scheme's beauty is that easily achieved by
the immature, like kittens, puppies, baby seals, etc -- it's like a
pedophile whose arrested sexual development has removed from him the
ability to find attraction in the mature.

avoid Scheme, but do know it first. the same goes for other languages
that made seriously misguided decisions at one point or another in their
youth, like C, Perl, etc. they have their uses, but the chance they
overlap with your needs is _very_ small. yet, you must learn to eschew
their mistakes: "small is beautiful" is actually reversed: it is ver
often the case the beautiful is small, but mere lack of size is no
guarantee of beauty. absence of features is _not_ good. unless, that
is, you're into job security and reimplementing several kinds of wheels
in incompatible ways -- then you will find Scheme even better than C and
Perl. _nothing_ is standard in Scheme, except for the ridiculously small
language core. it also appears to be much more fun to implement Scheme
than to actually use it. the useful Scheme systems are often larger than
the comparable Common Lisp systems, and this is no accident. small
languages require more verbiage to express the same ideas than large
languages do, and on top of that much smaller parts of the system has
been left to people who were paid _only_ to implement fundamentals well
and optimize them heavily. small languages violate the concept of
division of labor. only fools and geniuses insist on implementing their
own languages, and you can never tell which is which until afterwards.
in Scheme, as in C, every programmer has to be a genius, but often comes
out a fool because he is so far from competent at every task required.

I think I dislike Scheme more because of the way Scheme folks denigrate
Common Lisp, which they invariably haven't used, than anything else. a
language that does that to good people's minds should carry a warning
from the Surgeon General.

I know C very well and Scheme well. I became exhausted over the prospect
of doing the same low-level cruft over and over and over. Scheme is
often worse than C in this regard, because you will mostly find
interpreted Scheme environments, and abstraction carries a heavy
performance penalty, so you need to be much too clever. (this is like
byte-compiled Common Lisps, which penalize you severely for using your
own functions instead of the internal functions that are very heavily
optimized.)

if you really want to implement your own language, implement Scheme. if
you really want to _use_ a good language, choose Common LIsp. corollary:
implement Scheme in Common Lisp.

#:Erik
--
http://www.naggum.no/spam.html is about my spam protection scheme and how
to guarantee that you reach me. in brief: if you reply to a news article
of mine, be sure to include an In-Reply-To or References header with the
message-ID of that message in it. otherwise, you need to read that page.

David Steuber The Interloper

unread,
Sep 14, 1998, 3:00:00 AM9/14/98
to
On 13 Sep 1998 20:21:25 GMT, dje...@well.com (Darius Bacon) claimed or
asked:

% tras...@david-steuber.com (David Steuber "The Interloper") writes:
%
% >P.S. A pointer to an online resource that describes the differences
% >would be more than satisfactory.
%
% http://www.well.com/user/djello/scheme-for-lispers.html is a quick
% overview of what's needed for a Common Lisp user to understand a
% Scheme program.
%
% --
% Darius Bacon http://www.well.com/~djello

<blockquote>
What's Missing
Scheme lacks several standard facilities of a modern general-purpose
language: modules, exception-handling, a rich standard library, and an
object system. It's possible to build them all on top of the base
language with little extra support from the implementation, but
there's no consensus on what the resulting system should look like.
Scheme isn't likely to supplant CL for industrial-strength use;
instead it's most useful for research and education and as a glue
language for other systems.
</blockquote>

Presumably, I can implement the missing features (in theory). I don't
know that I have the knowledge to do the job. In order to
satisfactorily interact with the Java Runtime, I may need to do
multithreading, synchronization, exception handling, and packages
(modules). I would do that in the form of obvious implementation
specific extensions. If I go the compiler route (I've never even
written an interpreter let alone a compiler), I need to be able to
generate .class files in the format defined by "The Java Virtual
Machine Specification".

Guy Steele seems to show up all over the place. He invents Scheme, he
writes a Common Lisp ANSI standard book, and is co-author of "The Java
Language Specification."

I wonder if, with the support of some Java code, a Scheme compiler (or
CL) could be written to produce a .class file. The byte code and file
format is biased heavily towards Java. But it would be cool to see if
Scheme can be translated to Java byte code. It would be even cooler
to see what a Java decompiler makes of it.

Clearly CL is Schemes big brother in terms of size.

Brian M. Moore; esq.

unread,
Sep 14, 1998, 3:00:00 AM9/14/98
to
David Steuber "The Interloper (tras...@david-steuber.com) wrote:

: I wonder if, with the support of some Java code, a Scheme compiler (or


: CL) could be written to produce a .class file. The byte code and file
: format is biased heavily towards Java. But it would be cool to see if
: Scheme can be translated to Java byte code. It would be even cooler
: to see what a Java decompiler makes of it.

It is possible to compile a large subset of Scheme to Java
bytecodes. The result, however, is not properly tail-recursive,
as the JVM itself is not properly tail recursive. This is due to
restrictions in the security manager and classloader. There are
also restrictions on continuations captured with call/cc.

Per Bothner has created a compiler of this nature known as
Kawa. See http://www.cygnus.com/~bothner/kawa.html for more
details.


--
--Brian

+---------------------------------------------------------+
| Brian M. Moore procedural epistemologist |
| moo...@iname.com http://www.ukans.edu/home/mooreb |
+---------------------------------------------------------+

Klaus Schilling

unread,
Sep 14, 1998, 3:00:00 AM9/14/98
to
tras...@david-steuber.com (David Steuber "The Interloper") writes:
>
> I wonder if, with the support of some Java code, a Scheme compiler (or
> CL) could be written to produce a .class file. The byte code and file
> format is biased heavily towards Java. But it would be cool to see if
> Scheme can be translated to Java byte code. It would be even cooler
> to see what a Java decompiler makes of it.

Per Bothner from Cygnus Solutions is working on that . (Kawa project).


>
> Clearly CL is Schemes big brother in terms of size.

But Commion Lisp lacks call-with-current-continuation.

Klaus Schilling

Darius Bacon

unread,
Sep 14, 1998, 3:00:00 AM9/14/98
to
tras...@david-steuber.com (David Steuber "The Interloper") writes:

>I wonder if, with the support of some Java code, a Scheme compiler (or
>CL) could be written to produce a .class file.

Actually, no Java is needed -- there's Scheme code to read and write
classfiles on my home page.

Kent M Pitman

unread,
Sep 14, 1998, 3:00:00 AM9/14/98
to
[comp.lang.scheme removed. i don't cross-post and in fact i don't
usually reply to cross-posts. i'm only sending this at all because i
spent enough time on it before noticing it was a cross-post that i
didn't want to throw it away. see
http://world.std.com/~pitman/pfaq/cross-posting.html
for an explanation of why i don't participate in cross-posted
discussions.]

Klaus Schilling <Klaus.S...@home.ivm.de> writes:

> > Clearly CL is Schemes big brother in terms of size.
>
> But Commion Lisp lacks call-with-current-continuation.

You shouldn't assume all CL users are sad about this.

I, for one, am glad not to see continuations in CL. If someone
proposed adding them, I would argue strongly against the move. I feel
about them the same way as others feel about GO. They encourage
unstructured programming and I think they're a semantic mess. (No, I
don't mean they can't be defined in a formal semantics. I mean there
is no proof that being modelable in a formal semantics implies being a
good way for a human being to think about or describe something.)
Critically absent from continuations (i.e., procedurally embedded in
them, and therefore not always "apparent"--halting problems and all,
you know) is the answer to the question "is this the last time this
continuation will return?", which makes a mess of any attempt to
attach a rational semantics to unwind-protect. Scheme doesn't
offer unwind-protect, of course; it leaves it as an exercise to the
(human) reader. But you can see hints of how ugly the situation would be
in 6.6.1 Ports in the Revised^5 Report on Scheme by realizing that
unwind-protect or its equivalent is subprimitive to call-with-input-file,
and realizing the war between unwind-protect and continuations is what
leads to the mega-yuck wording there.

I argued vociferously to the Scheme committee that either Scheme
continuations should take an extra arg saying final-p or else
call-with-current-continuation should take an extra argsaying whether
the continuation given should be a one-time-use continuation (i.e.,
one that marks itself invalid after one use, allowing it to run its
unwinds at unwind time instead of later at gc time, which is--though
the scheme report doesn't say it outright--the only time the "proof"
can ever be done that the continuation is no longer in use) or a
multi-use continuation (i.e., one that never runs unwinds because it
might go "return again"). Either of those "fixes" would fix the
problem in a clean way. But the majority of authors of the Revised^N
Scheme Report seem to like the present definition of Scheme as is
because they're used to it, in spite of the mess I claim it makes.

I have often said that the way to tell a usable language is the
presence of unwind-protect. It's not just that unwind-protect is a
useful thing in and of itself, but its presence or absence says a
great deal about the mindset of a language's designers.

Don't get me wrong. I think the meta-notion of continuations offers
interesting expression/power. But so does GO. (Coincidentally, the
two are pretty related.) My point is that one doesn't have to deny its
expressiveness or flexibility, nor does one have to fail to understand
something, in order to not like it. So please no lectures about all
the wonders of call/cc. I understand the wonders. But I don't
put things in languages to make people wonder--I put them in because
they allow me to express things clearly. And absent a way of distinguishing
multi-use continuations from one-use continuations, or absent a way of
distinguishing non-final calls to continuation sfrom final calls,
the notion of call-with-current-continuation is broken.

Of course, we could put it into CL with a fix, but then it wouldn't
be compatible and people would still say we weren't Scheme's big brother
because we weren't buggy like Scheme is. So what's the point?

I'd rather have a working unwind-protect than scheme continuations any day.

Please don't forward this to comp.lang.scheme. This message is not
about what Scheme should do. I argue that elsewhere than in public
forums and don't want to stir it up with them again. Scheme will do
what Scheme will do and I for one am tired of beating my heaed against
the wall on it. My remarks here are offered only as an explanation of
why I think it's in CL's best interests not to follow Scheme's lead.
And perhaps as a partial explanation of why I'm so unimpressed by
people who insist on telling me that Scheme is more "noble" than CL
because of it so-called simplicity and its claim that somehow a
formal semantics makes it morally superior.

Enough controversy for one evening. Time for me to head off to bed.
--Kent

brl...@my-dejanews.com

unread,
Sep 14, 1998, 3:00:00 AM9/14/98
to
In article <6th9g5$qku$1...@its.hooked.net>,
> overview of what's needed for a Common Lisp user to understand a
> Scheme program.

Nice guide. As a schemer, I also found it useful for learning something about
CL.

One nit: Exclamation points are specifically about mutation, not side effects
in general. For example, the write and display procedures don't have
exclamation points.

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum

Mark Watson

unread,
Sep 14, 1998, 3:00:00 AM9/14/98
to
Hello everyone,

re:
>> Erik Naggum wrote:
> But Scheme does _not_ scale well.

Well, I must admit that I have never written any extremely
large systems in Scheme, but I think that I will strongly
disagree with this statement anyway! Years ago, at
SAIC, I used to spend about 1/4 of my time doing IR&D
projects (mostly NLP, some expert systems, reasoning,
etc.) in Common LISP and Scheme. (I have also written
two application-oriented LISP books for Springer-Verlag;
one in Common LISP, and one in Scheme).

I used a simple procedure in Scheme to keep moderately
large systems tidy: after I implement a framework that might
include a dozen or so functions (and debug them!), I used
to write a "wrapper" function, and copy all of the "worker"
functions into the "wrapper" function, using LEXICAL SCOPING
to keep my namespace clean (i.e., the worker functions are
now invisible to the global name space).

I could never think of a reason why this was a bad idea, and it
allowed me to keep systems tidy: especially important if I would
have to occasionally set aside work on a Scheme project for
a month or so.

-- Mark Watson www.markwatson.com

PS. I did do one large system in Scheme, but it was not really
my code: once I spent three long days converting OPS5 from
Common LISP to Scheme (it was an old Scheme dialect with a
built in "eval" function, so this was not too difficult - mostly
hand coding loops to use recursion).

Dimitrios Souflis

unread,
Sep 14, 1998, 3:00:00 AM9/14/98
to
Erik Naggum wrote:
>
> I think I dislike Scheme more because of the way Scheme folks denigrate
> Common Lisp, which they invariably haven't used, than anything else.
>

Every good programmer knows at least a handful of languages to get
along,
so a "Scheme folk" is rather an abstraction than an actual label.

Now, on the point.

Scheme is small. I guess R5RS is about one tenth the size of CLTL.
That makes it suitable for
1) scripting. Yes, people _need_ scripting. They do it in Perl,
Javascript
TCL, whatever.
2) embedded applications ? If Java can make it, why not Scheme?
3) explaining ideas simply

Like it or not, the mere size of a language can make a difference.
My first LISP was Acornsoft LISP. At the time, small was beautiful
for LISPers.

--
Dimitrios Souflis dsou...@altera.gr
Altera Ltd. http://www.altera.gr/dsouflis

*** Reality is what refuses to disappear when you stop believing
*** in it (VALIS, Philip K. Dick)

Barry Margolin

unread,
Sep 14, 1998, 3:00:00 AM9/14/98
to
In article <35FD2832...@altera.gr>,

Dimitrios Souflis <dsou...@altera.gr> wrote:
>Scheme is small. I guess R5RS is about one tenth the size of CLTL.
>That makes it suitable for
>1) scripting. Yes, people _need_ scripting. They do it in Perl,
>Javascript
>TCL, whatever.

What does the size of the language spec have to do with whether it's
suitable for scripting? Perl is one of the most popular scripting
languages, and its book is about the size of CLtL. Part of what makes it
popular is the wealth of built-in, high-level facilities (e.g. associative
arrays and regular expressions) -- also much more in the style of CL
(associative arrays are analogous to CL hash tables).

--
Barry Margolin, bar...@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.

Barry Margolin

unread,
Sep 14, 1998, 3:00:00 AM9/14/98
to
In article <87btoj5...@ivm.de>,

Klaus Schilling <Klaus.S...@home.ivm.de> wrote:
>But Commion Lisp lacks call-with-current-continuation.

call/cc is mostly usable for implementing higher-level control
abstractions. CL includes most of them as built-in features.

BTW, call/cc can be implemented as a macro in CL. It won't permit
returning from a block twice, but that's an overall limitation of CL, not
specific to call/cc. Basically, CL permits the dynamic control stack to be
a traditional stack, and only requires variable bindings to be saved in
heap-allocated lexical environments.

Rainer Joswig

unread,
Sep 14, 1998, 3:00:00 AM9/14/98
to

> Erik Naggum wrote:
> >
> > I think I dislike Scheme more because of the way Scheme folks denigrate
> > Common Lisp, which they invariably haven't used, than anything else.
> >
>
> Every good programmer knows at least a handful of languages to get
> along,
> so a "Scheme folk" is rather an abstraction than an actual label.
>
> Now, on the point.
>

> Scheme is small. I guess R5RS is about one tenth the size of CLTL.
> That makes it suitable for
> 1) scripting. Yes, people _need_ scripting. They do it in Perl,
> Javascript
> TCL, whatever.

We are using CL for scipting.

Dimitrios Souflis

unread,
Sep 14, 1998, 3:00:00 AM9/14/98
to
Barry Margolin wrote:
>
> What does the size of the language spec have to do with whether it's
> suitable for scripting? Perl is one of the most popular scripting
> languages, and its book is about the size of CLtL. Part of what makes it
> popular is the wealth of built-in, high-level facilities (e.g. associative
> arrays and regular expressions) -- also much more in the style of CL
> (associative arrays are analogous to CL hash tables).

I'm more concerned with extension languages, so the use of the word
"scripting" was somewhat misleading. But even for the ordinary,
Perlish meaning, having a smaller, orthogonal language
is worthy. Watch what Olin Shivers and others are doing with SCSH.

The size of the language spec is correlated to the size of the average
implementation. Perl is used for scripting, but
1) it must be fully installed on the machine (not everybody can/wants)
2) it's too big at runtime compared to a small program (yes, Apache does it)

My company is releasing v.2.0 of a small-footprint client-server SQL
server with embedded HTTP server. Had we used Perl as a scripting
language point (1) above would mean that installing our products
scripting language would double the disk requirements, and
point (2) that we would increase our memory requirements. Admit that
it would seem silly to have a scripting language comparable in size to
the rest of the program.

I'm not opposite to CL per se, but having to port a whole CLISP
implementation (we target Win32 and several Un*xes) would be a burden,
even if I knew of free CLISPs (pointers welcome).

Stig Hemmer

unread,
Sep 14, 1998, 3:00:00 AM9/14/98
to
The only certain conclusion to this debate is that crossposting
between comp.lang.lisp and comp.lang.scheme generates flame wars.

Please don't.

Stig Hemmer,
Jack of a Few Trades.

PS: Note followup.

Dorai Sitaram

unread,
Sep 14, 1998, 3:00:00 AM9/14/98
to
In article <sfw7lz7...@world.std.com>,

Kent M Pitman <pit...@world.std.com> wrote:
>
>I argued vociferously to the Scheme committee that either Scheme
>continuations should take an extra arg saying final-p or else
>call-with-current-continuation should take an extra argsaying whether
>the continuation given should be a one-time-use continuation (i.e.,
>one that marks itself invalid after one use, allowing it to run its
>unwinds at unwind time instead of later at gc time, which is--though
>the scheme report doesn't say it outright--the only time the "proof"
>can ever be done that the continuation is no longer in use) or a
>multi-use continuation (i.e., one that never runs unwinds because it
>might go "return again"). Either of those "fixes" would fix the
>problem in a clean way. But the majority of authors of the Revised^N
>Scheme Report seem to like the present definition of Scheme as is
>because they're used to it, in spite of the mess I claim it makes.

Some dozen years ago, Friedman and Haynes showed
(proved!) that call/cc-one-shot is no less expressive
than call/cc. Making continuations one-shot is not
going to make your headaches go away. The
Pitman/Naggum line should be drawn firmly at "escaping"
continuations. Beyond that, there be dragons.

--d


Frank Adrian

unread,
Sep 14, 1998, 3:00:00 AM9/14/98
to
>Clemens wrote in message ...
>>Dimitrios Souflis <dsou...@altera.gr> writes:

>> Scheme is small. I guess R5RS is about one tenth the size of CLTL.

>But you have to mention that the Common Lisp standard goes into great
>length of explaining things and giving examples and implementation
>hints. R5RS does not do this.

This is simply not true. The denotational semnatics section of R5RS gives
more detail than the Common Lisp standard does (and in a much less ambiguous
manner, as well). As for implementation hints, I really have to wonder if a
language standards document is a place for this, given that it should be
targeted towards the largest readership base, i.e., the language users,
rather than the implementors. Implementation pragmata belong in an
implementation manual, not in the standard.

P.S. Please don't take this as a slam against the CL standard. I am aware
that many people have different opinions as to what should go into a
standard and that the people who created the CL standard had a monumental
task in front of them. I just think that it is unfair to slam a standard
that (for the most part) is a benchmark for non-ambiguity, clarity, and
minimalism for not "explaining things" (which it clearly does) in a manner
that would lead to more ambiguity and verbosity.
--
Frank A. Adrian
First DataBank

frank_...@firstdatabank.com (W)
fra...@europa.com (H)

This message does not necessarily reflect those of my employer,
its parent company, or any of the co-subsidiaries of the parent
company.


Barry Margolin

unread,
Sep 14, 1998, 3:00:00 AM9/14/98
to
In article <6tjr3o$kab$1...@client2.news.psi.net>,

Frank Adrian <frank_...@firstdatabank.com> wrote:
>>Clemens wrote in message ...
>>>Dimitrios Souflis <dsou...@altera.gr> writes:
>
>>> Scheme is small. I guess R5RS is about one tenth the size of CLTL.
>
>>But you have to mention that the Common Lisp standard goes into great
>>length of explaining things and giving examples and implementation
>>hints. R5RS does not do this.
>
>This is simply not true. The denotational semnatics section of R5RS gives
>more detail than the Common Lisp standard does (and in a much less ambiguous
>manner, as well). As for implementation hints, I really have to wonder if a
>language standards document is a place for this, given that it should be
>targeted towards the largest readership base, i.e., the language users,
>rather than the implementors. Implementation pragmata belong in an
>implementation manual, not in the standard.

I haven't checked specifically, but I don't think the denotational
semantics includes details like branch cuts for mathematical functions. It
just covers basic control and data flow primitives. And by design,
Scheme's control and data flow primitives are relatively simple (virtually
everything can be defined in terms of lambda and call/cc), which is why
it's feasible to write a DS (X3J13 had as one of its original goals a DS
for Common Lisp, but the person we tasked with it gave up).

It's easy to be precise when you're describing something simple. CLtL
takes several pages just describing all the features of CL's lambda list
parameters (&OPTIONAL, &KEY, etc.).

Also, R*RS makes extensive use of references to other documents. For
instance, the macro section simply says that macros must be hygienic and
points the reader to a paper on this subject, rather than going into
extensive detail about what it means.

Kent M Pitman

unread,
Sep 14, 1998, 3:00:00 AM9/14/98
to
[oh, darn. i almost replied to another cross-posted conversation.
i gotta remember to killfile this conversation so it stops snagging me.
http://world.std.com/~pitman/pfaq/cross-posting.html
]

"Frank Adrian" <frank_...@firstdatabank.com> writes:

> As for implementation hints, I really have to wonder if a
> language standards document is a place for this, given that it should be
> targeted towards the largest readership base, i.e., the language users,
> rather than the implementors. Implementation pragmata belong in an
> implementation manual, not in the standard.

We discussed this explicitly. The standard is not an implementation
guide and I would never have thought to even suggest it gives
implementation advice. I guess it does sometimes offer sample
implementations, but not in enough quantity. In the original design
(pre X3J13), we referred to the "white pages" as the main document and
"yellow pages" as shared libraries" and there were red and blue pages
that were implementation notes and design rationales that were
supposed to happen but no color of pages ever emerged but the white
ones. We struck a balance by not designing the CL document as an
implementation guide, but we also didn't make a specific policy of
removing info just because it was useful to implementation.

It would probably not have been financially viable to make an
implementation guide. Only implementors care, and they all have a
financial stake. Unlike Scheme, CL is not about college, it's about
business. (I'm simplifying, yes. But to make a point.) Businesses
had big stakes in CL and the whole process was about stabilizing
investments, not creating new entrants into the market. Certainly all
vendors have been more helpful than they might be in many industries
when new entrants have tried to come along, so it's not a vicious
thing. It's just that coping with the task of stabilizing the
enormous investment which was already CL was very large. So it seemed
a shame to defer such information to an implementation guide that would
never come.

And to an extent I can recall discussions (not at X3J13 specifically
but in the Lisp community generally for years even predating the
standards work) where the key element was that languages don't need to
be implemented really a lot. Programs get written a lot, compared to
implementations. If people need to keep reimplementing the language,
there is either something wrong with the language or the key
contribution of the language is not the programs that people will
write because programs don't need infinite implementations to run on.
The idea in CL was to take a bunch of stuff people do over and over
and centralize that in one place so that it wasn't repeated by each
programmer. (Dick Gabriel, in his "worse is better" articles, argues
that this might not be a "good idea". But it doesn't make it not a
"possible idea".) There is a potential pitfall where people rely on
the "myth of the sufficiently clever compiler" (sometimes just "SCC")
to solve all problems. It's tough. You want to rely on things you
might not know how to do fully optimally today, and it's tricky drawing
the line. Scheme has a simlar problem. ("Adopt only one thing--Lambda--
and optimize it to pieces and hope that's enough") CL's problem is
slightly different. ("Adopt many things and optimize each according to
idiosyncratic but practically popular patterns of actual usage").
Anyway, that CL is hard to implement is not a suprising result--it's
almost designed in. What CL doesn't implement, users would have.
So it's a kind of modularity thing--better to do it centrally.
You might disagree it's the right approach, but your disagreement
would have to be pragmatic based on how you weigh the options.
I think in principle it's a solid theory, just different than the
path Scheme takes.

I model CL as the function f(x)=1000000*x and Scheme as the function
f(x)=0.000001*x^1.000001 where f is how well the language uses my
time and effort, represented somehow as x. Big-O notation
tells me Scheme should win, but it doesn't tell me whether Scheme
will win within my lifetime. Practicality tells me to use CL.

I liked Erik Naggum's advice to people wanting to implement a language,
that they should implement scheme, and to people wanting to use a language,
that they should use common lisp. The only thing I would add is that,
for the most part, since there seeems to be some confusion on the point,
it's more useful if people implement programs than languages.
Somewhere lost in the soup of all this discussion is that the only reason
computers exist is to better quality of life, and I personally want to
have done something to better my intrinsic quality of life before I die.
I've exhausted the quantum allocated to getting me the language necessary
to do that. You can, like the serfs of the middle ages, take solace in
the idea that you're improving the quality of life for people in some
subsequent era. But if you do, probably the best part of that plan will
be dying before you find out how much of whhat you could have contributed
you've wasted.

A few of us should implement languages. Big powerful languages
with big powerful compilers that do big important things that people
really need. The rest of us should get down to the business of finding
out whether computers can do anything other than be big paperweights
and enormous timesinks. So far, in all of computer science, the benefits
have been few compared to the number of people doing things. Most has
been frittered away by bad choice of programming language that tried
to be "minimal" instead of "functional". Yeah, there's the occasional
medical diagnosis program or desktop publishing thing or web browser.
But with the massive parallelism of human effort, we could be doing better.
And the key to that is not "just making sure we have the perfect language".
The cost of doing that if we'd applied that theory to english would be
the loss of everything from Homer's works to Shakespeare's to Tom Clancy.
Human languages are not perfect. But their value comes from our willingness
to agree on things and move on, whether in Spanish which mostly gets
verb conjugation right but has a dreadfully small vocabulary or in French
which has atrocious spelling but very pretty sound to it or in English which
is not pretty at all but very adaptable. The language characteristics don't
matter nearly as much as that certain basic power is there and people are
willing to just use it and get on with life. Any additional moralizing is
like that little committee that tries to decide if Spanish should add
this or that word to the language while English and other non-committee-run
languages outpace it in anarchisticly-organized expressiveness. Small and
pretty is nice if small and pretty is your goal. If usefulness is nice,
ask someone who's got a serious commitment to being a user and a real
goal of doing something other than design his whole life.

(Note: I tell people when they ask that I design programming languages, but
I always admit that languages are only designed cyclically and that most of
being a language designer is about writing applications so you'll know when
the next round of questions come up what things matter and what don't.
Because you don't get that by sitting in committee. So nine years out of
ten in being a langauge designer is not spent designing languages.)

> P.S. Please don't take this as a slam against the CL standard. I am aware
> that many people have different opinions as to what should go into a
> standard and that the people who created the CL standard had a monumental
> task in front of them. I just think that it is unfair to slam a standard
> that (for the most part) is a benchmark for non-ambiguity, clarity, and
> minimalism for not "explaining things" (which it clearly does) in a manner
> that would lead to more ambiguity and verbosity.

No offense taken. But I'll add another defense for CL as well.

The Scheme standard uses two independent languages which it claims have
the same implications. This is hard to test. The English is readable by
more people than the formal semantics, I bet. What if there is a bug?
Which prevails? Procedurally, we decided to drop as much of redundancy
as possible from the ANSI spec. It's why there is no chart of the
class arrangement, for example. If I made a mistake, would the chart be
right or the class precedence list in the class definition? In such a
big document, given that it was already written when started and was
merely morphed into shape (an engineering feat of its own), the cost of
removing all such redundancy was prohibitive. The most obvious place
you see this is in the inconsistent application of glossary terms. The
original goal was to use only italic (glossary terms) and never roman
(english terms). At the point where everything was in italic, we could
remove the italic and just say any use of a glossary word meant what the
glossary said. But it was too costly. So we made an engineering choice
and the result leaves you on each case having to know "did we think about
this sentence and this particular use of the glossary word" and if you
see it in italic, the answer is yes. (You can imagine the tedium and why
it took years for my predecessor, Kathy Chapman, who started the glossary
and for me who probably doubled its size and widened the scope of usage
in the running text.) It was an informal goal of the process to make
the standard not internally redundant. Medium success. It was an
informal goal of the process to make the standard accessible to a lay
audience, to allow the community as a whole to criticize it.

I, for example, can't read a formal semantics. I have, I think, a
clear understanding of what it offers. But I hate the notation and
have never been good at infix, and have never had the patience to slug
through learning it well enough to apply reasoning about it at any
speed. (I consider it a bug that the formal semantics is not
s-expression-based. Ah well. Ironic,m perhaps, that my semantic
understanding of scheme should be so impaired by syntax, as ones
usually thinks of the point of a semantics to separate the language
from its syntax.) So I occasionally trip over something that is not
well-specified in the Scheme standard and get in an argument over
whether it's well-specified in the standard because it's in the formal
semantics. Some probably think this means I'm weak-mineded and my
opinion shouldn't be counted about Scheme. Maybe so. But there are
more weak-minded people where I came from, and I'm happy to support
those of us more feeble members of the society who are disenfranchised
by the use of a formal semantics. As such, I reject any claim that
the use of English is what makes the CL spec not clear. I think
English is up to the task. Time, budget, and the author's skill
is another matter. I will happily apologize for the places where
my English didn't leave it in a perfect state. But I don't think
going to half-English/half-formal-semantics fixes the problem. It
doesn't get rid of the English, AND it adds the possibility of
a confusion where one half says one thing and one says another.
To solve this, I'm told some other standards are written without English.
I have not seen it, but I'm told PL/1 (I think it was) had a definition
written in a formal language (only). Yuck.

Use of English brings the language to the users rather than requiring
the users to come to the language. (Sorry it's English. That's just
the international interchange convention. The ambiguity of talking
about my own language where I mean "the canonical natural language" is
embarassing to me sometimes. Do understand I'm aware there are other
languages out there. I even speak a couple of them.) Anyway, I think
in general computers do all too much of making people think like
machines instead of vice versa, and I'm proud to have been involved
in a little push in the other direction.

Moreover, languages don't exist in isolation. I consider it an
essential criterion of a programming language that its constructs be
pronounceable (hence my indulging a pronunciation guide in a few
places where a dictionary would not have one) and that people have
useful interchange terms for common situations (hence the 70 page
glossary--itself longer than the scheme spec). When it was done, I
looked through it and said "gee, this is big. " but then i looked for
terms that weren't already in common use and there weren't many. the
few there were (like "designator" and "generalized boolean", which i
made up) were concepts already present but just in search of a name.
So I regarded this as a process of helping programmers interchange,
not just programs. It didn't need that justification. Just the
saved text size of making the definitions centralized was enough.
(And I'd have had to invent a lot more terms if I hadn't overloaded
terms exactly as they're overloaded in English.) But it was still
nice to know it was contributing to stabilizing the terminology
in the culture.

This is really longer than I meant it to be. Sorry about that.
If I had more time I'd shorten it.

The above is my personal opinion and not necessarily the official
position of my company or country.

Jrm

unread,
Sep 14, 1998, 3:00:00 AM9/14/98
to

>I have often said that the way to tell a usable language is the
>presence of unwind-protect. It's not just that unwind-protect is a
>useful thing in and of itself, but its presence or absence says a
>great deal about the mindset of a language's designers.


What about dynamic-wind?

>Please don't forward this to comp.lang.scheme.

That'll keep 'em in the dark.


Jrm

unread,
Sep 14, 1998, 3:00:00 AM9/14/98
to

Kent M Pitman wrote in message ...

>I liked Erik Naggum's advice to people wanting to implement a language,
>that they should implement scheme, and to people wanting to use a language,
>that they should use common lisp.

I made more money when I hacked common lisp, but I have more fun when I
hack scheme.

(/ (- (f common-lisp) (f scheme)) (f C)) => float underflow

David Steuber The Interloper

unread,
Sep 15, 1998, 3:00:00 AM9/15/98
to
On 14 Sep 1998 08:17:01 GMT, dje...@well.com (Darius Bacon) claimed or
asked:

% tras...@david-steuber.com (David Steuber "The Interloper") writes:
%
% >I wonder if, with the support of some Java code, a Scheme compiler (or
% >CL) could be written to produce a .class file.
%
% Actually, no Java is needed -- there's Scheme code to read and write
% classfiles on my home page.

Can the Scheme code compile itself to run in the JVM?

David Steuber The Interloper

unread,
Sep 15, 1998, 3:00:00 AM9/15/98
to
On 13 Sep 1998 19:33:06 +0000, Erik Naggum <cle...@naggum.no> claimed
or asked:

% I know C very well and Scheme well. I became exhausted over the prospect
% of doing the same low-level cruft over and over and over. Scheme is
% often worse than C in this regard, because you will mostly find
% interpreted Scheme environments, and abstraction carries a heavy
% performance penalty, so you need to be much too clever. (this is like
% byte-compiled Common Lisps, which penalize you severely for using your
% own functions instead of the internal functions that are very heavily
% optimized.)
%
% if you really want to implement your own language, implement Scheme. if
% you really want to _use_ a good language, choose Common LIsp. corollary:
% implement Scheme in Common Lisp.

It seems to be implied that if you want to implement Common Lisp, it
should be done in Common Lisp. Also, why can't byte compiled Common
Lisp optimize your functions as well as its own?

I should have just made up my mind before being confused with the
facts.

One requirement I can safely say I have is that I need to be able to
express constructs of arbitrary complexity in a uniform way. I also
need to be able to compile or interpret the code. The other main
thing I need to do is generate code. I have already decided that it
would be highly desirable from a code reuse point of view to use which
ever Lisp I go with as a file format as well as an extension or
scripting language.

I have to wonder how much of Common Lisp must be implemented as
native, and how much can be implemented in Common Lisp.

As far as inventing languages goes, I would really, really, like to
avoid that. It is already beyond anything I have done to implement a
language that already has a specified standard. To invent a language,
at least a good one, must be more difficult still.

Paul Graham says in his book that one of the features of Common Lisp
is that it can extend itself. I am only a little way into the book,
but I like what I have seen so far. I just wish I had a free ANSI
Common Lisp implementation on NT that I could play with his examples
on. Any recommendations?

Barry Margolin

unread,
Sep 15, 1998, 3:00:00 AM9/15/98
to
In article <35ffc713....@news.newsguy.com>,

David Steuber "The Interloper" <tras...@david-steuber.com> wrote:
>I have to wonder how much of Common Lisp must be implemented as
>native, and how much can be implemented in Common Lisp.

Take a look at one of the Common Lisp implementations where source is
available, such as CMUCL, and I think you'll find that an enormous number
of the functions are implemented in CL. Most of the sequence and list
functions, hash tables, the reader and printer, CLOS, the condition system,
and the evaluator are frequently implemented as library functions in Lisp.
Probably more than half the functions in CL.

Kent M Pitman

unread,
Sep 15, 1998, 3:00:00 AM9/15/98
to
"Jrm" <j...@rebol.com> writes:

> >I have often said that the way to tell a usable language is the
> >presence of unwind-protect. It's not just that unwind-protect is a
> >useful thing in and of itself, but its presence or absence says a
> >great deal about the mindset of a language's designers.
>
> What about dynamic-wind?

In spite of the implementation similarity, they don't implement the
same things. what unwind-protect implements is the concept of
"remember to clean up when i'm done". this is an enormously simple
and basic thing people say and do all the time. it is presented
as system magic becuase it becomes associated with stacks
or continuations, but it has nothing to do with these--it merely
interacts with them. "when i'm done" is adequate to describe
the "when" for most people. anything else is mere refinement.

by contrast, dynamic-wind implements "remember to save and
restore this state each time i'm working on a certain project"
mostly people streamline their activities to avoid state changes,
so they don't find needs to articulate descriptions of state changes
because they work to make them not happen. i'm talking about the
real world, not computers. projects and task interleaving do occur
in the real world but are rarer than just projects un-interleaved.

my comment was NOT meant to say that other operators aren't useful.
just that i think unwind-protect is primitively important even to
non-programmers in routine and very mundane tasks in ways that dynamic
wind is not. i think unwind-protect is "conceptually more primitive"
(in that most people have the concept before learning how to
articulate computerized computation) than dynamic wind (where i think
many people don't have the concept until taught to think tha way).
i'm not making a statement about the relative usefulness of these
operators per se. i'm saying that a decision by a language to deny
the ability to express a "conceptually primitive" concept is more
telling than a decision to deny a "learned" concept.

just my opinion. you're welcome to disagree. (i've never heard
anyone agree with me, actually. it's a pretty odd "test" for a
language, i guess. but it's one that has held up for me over time.)

if you don't like my suggestion, though, what small test or tests what
ould do if someone tossed you a manual to look at for ten minutes and
then to say if the language you were looking at was thoughtful?

Darius Bacon

unread,
Sep 15, 1998, 3:00:00 AM9/15/98
to
tras...@david-steuber.com (David Steuber "The Interloper") writes:

>On 14 Sep 1998 08:17:01 GMT, dje...@well.com (Darius Bacon) claimed or
>asked:

>% tras...@david-steuber.com (David Steuber "The Interloper") writes:
>%
>% >I wonder if, with the support of some Java code, a Scheme compiler (or
>% >CL) could be written to produce a .class file.
>%
>% Actually, no Java is needed -- there's Scheme code to read and write
>% classfiles on my home page.

>Can the Scheme code compile itself to run in the JVM?

No. If I had that I'd probably be advertising it a bit more
heavily. :) It's just a no-frills classfile parser/unparser, which you
could use to bootstrap such a compiler without writing a line of Java.
I also have some Scheme code with a table of JVM opcodes, their stack
effects and operands, etc., but it didn't really seem worth releasing.
Write me if you have a burning desire to see it anyway.

(What's this doing in comp.lang.lisp?)

Barry Margolin

unread,
Sep 15, 1998, 3:00:00 AM9/15/98
to
In article <sfwlnnl...@world.std.com>,

Kent M Pitman <pit...@world.std.com> wrote:
>"Jrm" <j...@rebol.com> writes:
>> What about dynamic-wind?
>
>In spite of the implementation similarity, they don't implement the
>same things. what unwind-protect implements is the concept of
>"remember to clean up when i'm done".
...

>by contrast, dynamic-wind implements "remember to save and
>restore this state each time i'm working on a certain project"

Well, they seem conceptually similar, given the context of the languages.
Common Lisp doesn't let you resume a dynamic environment after you've
exited, so it's only necessary to clean up. Scheme's continuations allow
you to go back in, so you need to clean up when exiting and "messy up" when
resuming.

If you're not planning on resuming, you can simply provide a a function
that signals an error as the before-thunk to dynamic-wind, and you have
something equivalent to unwind-protect.

Erik Naggum

unread,
Sep 15, 1998, 3:00:00 AM9/15/98
to
* tras...@david-steuber.com (David Steuber "The Interloper")

| It seems to be implied that if you want to implement Common Lisp, it
| should be done in Common Lisp. Also, why can't byte compiled Common Lisp
| optimize your functions as well as its own?

because the byte-code interpretation machinery must add _some_ overhead
to the execution, and the more byte-code, the slower it runs, as in
wholly user-defined functions. the more stuff is implemented in the real
implementation language, the faster it runs. this skews the way people
look at performance, and which features they'll use. when abstraction is
expensive, people don't do it. when abstraction is cheaper than not
doing it, the benefits become more obvious.

| I should have just made up my mind before being confused with the facts.

that's always good advice when the world is too complex to answer one's
questions simply. (I think it helps to understand complexity and then go
back and decide to ignore some of it, but far too many frown at the
complexity of the world and actively denounce tools and languages and
techniques intended to deal with it.)

| I have to wonder how much of Common Lisp must be implemented as native,
| and how much can be implemented in Common Lisp.

this depends on how you implement your "native" functions. it's possible
to write a proto-Lisp that a simple compiler compiles to machine code and
then implement enough Common Lisp in proto-Lisp to be able to build a new
system entirely in Common Lisp. (this proto-Lisp can in fact be another
language entirely, but then it's _more_ work to build the compiler.)

| Paul Graham says in his book that one of the features of Common Lisp is
| that it can extend itself. I am only a little way into the book, but I
| like what I have seen so far. I just wish I had a free ANSI Common Lisp
| implementation on NT that I could play with his examples on. Any
| recommendations?

why do you need NT? it takes less effort to install Linux and run
Allegro CL 5.0 Trial Edition (an uncrippled version recently released)
than it takes to find something free and high quality under NT.

#:Erik
--
http://www.naggum.no/spam.html is about my spam protection scheme and how
to guarantee that you reach me. in brief: if you reply to a news article
of mine, be sure to include an In-Reply-To or References header with the
message-ID of that message in it. otherwise, you need to read that page.

Kent M Pitman

unread,
Sep 15, 1998, 3:00:00 AM9/15/98
to
Barry Margolin <bar...@bbnplanet.com> writes:

> In article <sfwlnnl...@world.std.com>,
> Kent M Pitman <pit...@world.std.com> wrote:
> >"Jrm" <j...@rebol.com> writes:
> >> What about dynamic-wind?
> >
> >In spite of the implementation similarity, they don't implement the
> >same things. what unwind-protect implements is the concept of
> >"remember to clean up when i'm done".
> ...
> >by contrast, dynamic-wind implements "remember to save and
> >restore this state each time i'm working on a certain project"
>
> Well, they seem conceptually similar, given the context of the languages.
> Common Lisp doesn't let you resume a dynamic environment after you've
> exited, so it's only necessary to clean up. Scheme's continuations allow
> you to go back in, so you need to clean up when exiting and "messy up" when
> resuming.


i've seen ports of lisp machine letf (uses dynamic-wind style technology)
to use letf-globally (uses approximately unwind-protect) instead
and it makes a mess. people tend to debug it in single-processing mode
and then get screwed in multitasking.

When using the word conceptually, though, I was
talking about how human beings describe processes in the real world.
My point was that humans don't have (that they speak about) stacks,
so when they do context switches, they don't do (that they speak of)
this operation. Consequently, linguistically, they do not use these
terms "primitively" (without training to do so). The world is indeed
prone to having re-entrant processes. People might read a book and
watch TV, for example. But where state changes are required, people
try (i observe informally) to avoid having to do the state change
(see the literature on "practice effects" and think about the kinds of
optimizations people make to operations). if i use reading glasses
to read, i don't want to read and watch TV at the same time because
i have to keep putting on and removing my glasses. i avoid that.
or i invent bifocals so that i don't have to change them in between.
but either way, i avoid the need to linguistically discuss the state
change. human linguistics is driven by experience, not vice versa.
you can try to teach people terms they have no experience about in order
to broaden their horizons, but in my opinion all but the intellectual
class will resent you for it. all just my armchair observations
and conclusions-of-the-day. feel free to disagree. i may be wrong
about the data or wrong about the conclusions that it's not linguistic,
but those are both premises to my real claim which is that if
you believe (as i do, right or wrong) that dynamic-wind is not
"conceptually primitive", then you understand why it is that i
think it's not as fundamental a "tell" to the thoughtfulness
of the language in other regards.

as to the usefulness of dynamic-wind, i'm not saying it's unimportant.
ever since i heard about it in 1981, i've repeatedly reminded people
of its existence and advocated its adoption on occasion. it doesn't
just trouble me that it's absent. it also troubles me that "places"
aren't just as good as "variables" in special binding. if you believe
in special binding at all, and i do, it should seem clear that it's
about "the process of dynamically instantiating within a task that is
possibly interleaved with other tasks for which the dynamic instantiation
has not been done" and that doing it only for symbols is a hack
reminiiscent of maclisp sublis, which as i recall (might be wrong)
only allowed you to sublis for symbols because it was possible to
attach a property to symbols (and not to all objects) allowing
constant (or almost that) time access to the substitution object.
So instead of O(m*n) performance [a size m object and n replacements]
you'd get O(m). But at the price that you couldn't sublis other
objects at all. If they'd just fallen out to using alists or
hash tables or some such in the other case, it could have been defined
on anything. (Some have made the same criticism about GET and
property lists.)

optimization is important, but it shouldn't come at the price of not
allowing the unoptimized cases. there may be ways to optimize other
cases in the future and the language should plan for that, leaving it
to users to make a judgment about which features they exercise at what
point in time based on their market needs.

> If you're not planning on resuming, you can simply provide a a function
> that signals an error as the before-thunk to dynamic-wind, and you have
> something equivalent to unwind-protect.

"Resuming" happens on stack group switch. unless you're going to
turn off scheduling to avoid the resuming, you're going to lose with
this approach unless i misunderstand you. as soon as your quantum is
exhausted, the dynamic-wind after-thunk is going to run, which may
be ok in some cases and not in others, and as soon as you get
rescheduled, you'll be in the error handler (perhaps in the scheduler).
Or am I not understanding you?

Steve Gonedes

unread,
Sep 15, 1998, 3:00:00 AM9/15/98
to

tras...@david-steuber.com (David Steuber "The Interloper") writes:


< Paul Graham says in his book that one of the features of Common Lisp
< is that it can extend itself. I am only a little way into the book,
< but I like what I have seen so far. I just wish I had a free ANSI
< Common Lisp implementation on NT that I could play with his examples
< on. Any recommendations?

CLISP will run under DOS and windows. Also there is LispWorks for
windows (I think it will work with the New Technology - as windows
always seems to take an aggresive stance to be backwards compatibe :)

I have no url for LispWorks (sorry) maybe someone will shout it out;
a search engine will certainly pick it up.

Enjoy the rest of your book.

Mike McDonald

unread,
Sep 15, 1998, 3:00:00 AM9/15/98
to
In article <g0nL1.33$yt.5...@burlma1-snr1.gtei.net>,

Barry Margolin <bar...@bbnplanet.com> writes:
> In article <35ffc713....@news.newsguy.com>,
> David Steuber "The Interloper" <tras...@david-steuber.com> wrote:
>>I have to wonder how much of Common Lisp must be implemented as
>>native, and how much can be implemented in Common Lisp.
>
> Take a look at one of the Common Lisp implementations where source is
> available, such as CMUCL, and I think you'll find that an enormous number
> of the functions are implemented in CL. Most of the sequence and list
> functions, hash tables, the reader and printer, CLOS, the condition system,
> and the evaluator are frequently implemented as library functions in Lisp.
> Probably more than half the functions in CL.

With the exception of the code to call into/out of C/Lisp, some low level
interrupt and mmap C code, all of CMUCL is written in lisp. Having to have a
working CL inorder to get a working CL makes bootstrapping CMUCL lots of fun!
:-)

Mike McDonald
mik...@mikemac.com


Gary T. Leavens

unread,
Sep 15, 1998, 3:00:00 AM9/15/98
to
This may not be what you're looking for,
but here's a handout I use in my classes...

PRINCIPLES OF PROGRAMMING LANGUAGES:
COMMON LISP VS. SCHEME

Gary T. Leavens, Department of Computer Science,
Iowa State University, Ames, Iowa 50011-1040 USA
lea...@cs.iastate.edu
$Date: 1995/09/23 18:38:01 $

The table below highlights the important differences between
Common Lisp and Scheme for those that know a more standard
Lisp dialect. Only the differences are highlighted here,
there are many more similarities.

Common Lisp Scheme
-------------------------------------------------------
() ; eq to nil ()
nil #f
t #t

(eq x y) (eq? x y)
(equal x y) (equal? x y)

(atom x) (not (pair? x))
(consp x) (pair? x)
(null x) (null? x)
(symbolp x) (symbol? x)
(zerop x) (zero? x)

(setf (car x) y) (set-car! x y)
(setf (cdr x) y) (set-cdr! x y)

(mapcar #'f l) (map f l)
(map 'list #'f l) (map f l)

(mapcar #'(lambda (x) (g x)) l) (map (lambda (x) (g x)) l)

#'(lambda (x) y) (lambda (x) y)

(setq var y) (set! var y)
(setf var y) (set! var y)

(cond (cond
((null x) 0) ((null? x) 0)
((eq x y) (f x)) ((eq? x y) (f x))
(t (g y))) (else (g y)))

(defun square (x) (define (square x)
(* x x)) (* x x))
; or
(define square (lambda (x) (* x x)))

(funcall (g f) x) ((g f) x)

(defun compose (f g) (define (compose f g)
#'(lambda (x) (lambda (x)
(funcall f (f (g x))))
(funcall g x))))


Acknowledgments

Thanks to Erik Naggum and Richard Gabriel for correcting my ancient
LISP accent. Of course any errors are not their responsibility but mine.

Gary
--
229 Atanasoff Hall, Department of Computer Science
Iowa State Univ., Ames, Iowa 50011-1040 USA
lea...@cs.iastate.edu phone: +1 515 294-1580 fax: +1 515 294-0258
URL: http://www.cs.iastate.edu/~leavens/homepage.html

Jrm

unread,
Sep 15, 1998, 3:00:00 AM9/15/98
to

Kent M Pitman wrote in a message ...
[comparison about dynamic-wind elided]

I think I agree with Barry (barmar) that it is pretty easy to view
unwind protect as a dynamic-wind with an empty entry thunk (in
most cases).

I was just concerned with the the syllogism:

1. Languages without unwind-protect are not well thought out.
2. Scheme doesn't have unwind protect.

I know you disagree with much of what the Scheme people say, but
you can't say they don't think about what they are doing.

>if you don't like my suggestion, though, what small test or tests what
>ould do if someone tossed you a manual to look at for ten minutes and
>then to say if the language you were looking at was thoughtful?

I look for the ability to write continuation-passing style code without
too much pain. If you can do that, then the language is pretty powerful
even if the designers didn't intend or understand it. (I use the term
"designer"
losely; too many languages these days are not designed in any sense of the
word)

Barry Margolin

unread,
Sep 15, 1998, 3:00:00 AM9/15/98
to
In article <LJwL1.1820$K02.1...@news.teleport.com>,

Mike McDonald <mik...@mikemac.com> wrote:
> With the exception of the code to call into/out of C/Lisp, some low level
>interrupt and mmap C code, all of CMUCL is written in lisp. Having to have a
>working CL inorder to get a working CL makes bootstrapping CMUCL lots of fun!
>:-)

So how do you implement CAR and CDR in Lisp? I recall that Lisp Machines
had definitions like:

(defun car (x)
(car x))

and then depend on the compiler to generate the appropriate code. I don't
really think these trivial cases count. Nor would LAP. I'm not sure
whether to count "subprimitives", e.g. something like:

(defun car (x)
(case (system:%typecode x)
((1) (system:%memory-ref x 0)) ; cons
(t (error ...))))
(defun car (x)
(case (system:%typecode x)
((1) (system:%memory-ref x 1)) ; cons
(t (error ...))))

Barry Margolin

unread,
Sep 15, 1998, 3:00:00 AM9/15/98
to
In article <6tm5us$6pr$1...@news.iastate.edu>,

Gary T. Leavens <lea...@cs.iastate.edu> wrote:
>#'(lambda (x) y) (lambda (x) y)

FYI, ANSI Common Lisp includes a LAMBDA macro so that #' is no longer
needed for lambda expressions. Essentially it's

(defmacro lambda ((&rest arglist) &body body)
`#'(lambda (,@arglist) ,@body))

But it's probably good to have it in the table, since you're likely to see
it in old code (and new code by people who want to be portable to old
environments, don't like the macro, or just can't break the habit).

It would probably be a good idea to show an example of #'<function-name> in
the table. Perhaps after the definitions of compose, you could demonstrate
this in a use:

CL:

(defun *-+ (x y)
(funcall (compose #'* #'+) x y)

Scheme:

(define (*-+ x y)
((compose * +) x y))

Barry Margolin

unread,
Sep 15, 1998, 3:00:00 AM9/15/98
to
In article <sfwvhmp...@world.std.com>,

Kent M Pitman <pit...@world.std.com> wrote:
>Barry Margolin <bar...@bbnplanet.com> writes:
>> If you're not planning on resuming, you can simply provide a a function
>> that signals an error as the before-thunk to dynamic-wind, and you have
>> something equivalent to unwind-protect.
>
>"Resuming" happens on stack group switch. unless you're going to
>turn off scheduling to avoid the resuming, you're going to lose with
>this approach unless i misunderstand you. as soon as your quantum is
>exhausted, the dynamic-wind after-thunk is going to run, which may
>be ok in some cases and not in others, and as soon as you get
>rescheduled, you'll be in the error handler (perhaps in the scheduler).
>Or am I not understanding you?

How did stack groups and quanta enter this discussion? By "resuming" I
meant "re-entering the dynamic environment". Sure, Scheme continuations
provide a way to implement coroutines, but if you're not planning on
re-entering the routine then the continuation is just an escape procedure,
like CL THROW or RETURN-FROM. Basically, I think I'm referring to the same
kind of distinction you made a day or two ago about one-shot continuations
-- there's no need to provide a useful before-thunk if you're escaping the
dynamic-wind via a one-shot continuation.

Mike McDonald

unread,
Sep 15, 1998, 3:00:00 AM9/15/98
to
In article <HJxL1.46$yt.8...@burlma1-snr1.gtei.net>,

Barry Margolin <bar...@bbnplanet.com> writes:
> In article <LJwL1.1820$K02.1...@news.teleport.com>,
> Mike McDonald <mik...@mikemac.com> wrote:
>> With the exception of the code to call into/out of C/Lisp, some low level
>>interrupt and mmap C code, all of CMUCL is written in lisp. Having to have a
>>working CL inorder to get a working CL makes bootstrapping CMUCL lots of fun!
>>:-)
>
> So how do you implement CAR and CDR in Lisp? I recall that Lisp Machines
> had definitions like:
>
> (defun car (x)
> (car x))

Yup, that's what it does.

(defun car (list) "Returns the 1st object in a list." (car list))

> and then depend on the compiler to generate the appropriate code. I don't
> really think these trivial cases count.

Well, since the compiler and its optimizations are written in lisp, seems
close enough for me. :-)

>Nor would LAP. I'm not sure
> whether to count "subprimitives", e.g. something like:
>
> (defun car (x)
> (case (system:%typecode x)
> ((1) (system:%memory-ref x 0)) ; cons
> (t (error ...))))
> (defun car (x)
> (case (system:%typecode x)
> ((1) (system:%memory-ref x 1)) ; cons
> (t (error ...))))

This seems reasonable to me too. Sure, at some point, you have to have some
primitives that the compiler "knows" about or some "foreign" implementation of
them.

BTW, shouldn't this last one be cdr?

Mike McDonald
mik...@mikemac.com


Gareth McCaughan

unread,
Sep 15, 1998, 3:00:00 AM9/15/98
to
Barry Margolin wrote:

> It would probably be a good idea to show an example of #'<function-name> in
> the table. Perhaps after the definitions of compose, you could demonstrate
> this in a use:
>
> CL:
>
> (defun *-+ (x y)
> (funcall (compose #'* #'+) x y)
>
> Scheme:
>
> (define (*-+ x y)
> ((compose * +) x y))

But preferably not that example, since it won't work. (Evaluating
(*-+ x y) will try to apply (lambda (x) ...) to args x and y.) :-)
Oh, and emacs just bracket-matched the rparen in my smiley with
the lparen before "defun", so it looks like something's wrong
with the parentheses in the CL definition of *-+.

(Yes, of course I know these are trivial errors.)

--
Gareth McCaughan Dept. of Pure Mathematics & Mathematical Statistics,
gj...@dpmms.cam.ac.uk Cambridge University, England.

David Rush

unread,
Sep 15, 1998, 3:00:00 AM9/15/98
to
lea...@cs.iastate.edu (Gary T. Leavens) writes:
> (funcall (g f) x) ((g f) x)
>
> (defun compose (f g) (define (compose f g)
> #'(lambda (x) (lambda (x)
> (funcall f (f (g x))))
> (funcall g x))))

For my money, these two examples are nearly my *entire* reason for
preferring Scheme over CL. call-with-current-continuation is the rest
of it, although call/cc is not of very commonly useful.

Then again, I also really like Smalltalk and SML.

david rush
--
Unfortunately nobody will *pay* for much besides C/C++ (bleah)

Gary T. Leavens

unread,
Sep 15, 1998, 3:00:00 AM9/15/98
to
Barry Margolin <bar...@bbnplanet.com> writes:

>In article <6tm5us$6pr$1...@news.iastate.edu>,
>Gary T. Leavens <lea...@cs.iastate.edu> wrote:
>>#'(lambda (x) y) (lambda (x) y)

>FYI, ANSI Common Lisp includes a LAMBDA macro so that #' is no longer
>needed for lambda expressions. Essentially it's

>(defmacro lambda ((&rest arglist) &body body)
> `#'(lambda (,@arglist) ,@body))

>But it's probably good to have it in the table, since you're likely to see
>it in old code (and new code by people who want to be portable to old
>environments, don't like the macro, or just can't break the habit).

Thanks, I didn't know that.

>It would probably be a good idea to show an example of #'<function-name> in
>the table. Perhaps after the definitions of compose, you could demonstrate
>this in a use:

>CL:

>(defun *-+ (x y)
> (funcall (compose #'* #'+) x y)

>Scheme:

>(define (*-+ x y)
> ((compose * +) x y))

I put in the folowing:

(defun my-cadr (ls) (define my-cadr (ls)
(funcall ((compose car cdr)
(compose #'car #'cdr) ls))
ls))

I thought that composing two functions that are usually considered binary
would be confusing.

Thanks for the help,

Gary Leavens

Frank Adrian

unread,
Sep 15, 1998, 3:00:00 AM9/15/98
to
Mike McDonald wrote in message ...

> This seems reasonable to me too. Sure, at some point, you have to have
some
>primitives that the compiler "knows" about or some "foreign" implementation
of
>them.

If you want to know how another language implementation group did this (for
another language) check out the Squeak page at http://squeak.cs.uiuc.edu/,
especially the HTML version of the OOPSLA paper "Back to the Future"
(ftp://st.cs.uiuc.edu/Smalltalk/Squeak/docs/OOPSLA.Squeak.html).
All-in-all, a reasonable paper on bootstrapping a language in general (even
if the language they bootstrap into is incurably low-level :-).

Phil Stubblefield

unread,
Sep 15, 1998, 3:00:00 AM9/15/98
to Gary T. Leavens
Gary T. Leavens wrote:
>
> Barry Margolin <bar...@bbnplanet.com> writes:
>
> >It would probably be a good idea to show an example of
> >#'<function-name> in the table. [...]

>
> I put in the folowing:
>
> (defun my-cadr (ls) (define my-cadr (ls)
> (funcall ((compose car cdr)
> (compose #'car #'cdr) ls))
> ls))

It might make sense to change the name of the CL parameter from "ls"
to "list". Another poster said that the lack of funcall and #' was
nearly his entire reason for preferring Scheme over CL. In the same
vein, I can imagine many newcomers looking at these examples and
questioning the additional cruft on the CL side. The answer, of
course, is that this cruft is the cost you pay for the luxury of
separate namespaces for "variable values" and "function values," if
I may use that terminology. Changing the name of the CL parameter
to "list" helps the examples to spotlight the strengths and
weaknesses of the different approaches taken by the two languages.


Phil Stubblefield
Rockwell Palo Alto Laboratory 650/325-7165