[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Kent Dybvig's comments (long message)
Thank you for your comments on the preliminary draft. I see you have
received responses from Bill Rothas and from Chris Hanson. My remarks
below were complete in draft form before I saw their remarks. I wish
you had been able to attend the workshop, because your points of view
would have enriched some of the discussions.
Your (lambda name formals . body) syntax is equivalent to the optional
(named-lambda (name . formals) . body) syntax. As you observe, your syntax
conflicts with the (lambda x ...) syntax, which together with the
(lambda (x y . z) ...) syntax has been in MIT Scheme for perhaps five years,
and has been used in T for three years. The named-lambda syntax has
been in MIT Scheme for at least two years.
The named-lambda syntax was not very controversial at the workshop, since of
the implementations represented there only MIT Scheme uses it. I feel that
(rec name (lambda formals . body)) is better because it is more general, but
named-lambda was made an optional feature as a concession to MIT Scheme and
to simple compilers that might not be able to compile the rec form as well
as the named-lambda.
The syntax for rest arguments was opposed vigorously by one person, who
argued for (mulambda x . body) as the only way to obtain rest arguments.
His proposal would have been compatible with your syntax, but he was unable
to muster additional support for his position even though he argued the
matter at length. One of his arguments was that destructuring was a can of
worms that we shouldn't get into; apparently he was the only one at the
workshop who thought of the dotted pair syntax as indicating a
destructuring, however -- the rest of us viewed it as syntax pure and simple.
The &rest syntax was mentioned once but no one at the workshop felt like
arguing in its favor. I think most people at the workshop are repelled by
the complexity of Common Lisp's formal argument lists, and don't want to
have anything that even looks like them. In addition the &rest is less
visible than a period because it looks so much like an identifier.
As for requiring that all lambdas be named, I think you'd have about as much
luck convincing people of that as you would convincing people that all
integer constants should be named. Much of the beauty of functional
programming derives from anonymous procedures.
Other Special Forms
1. When programming imperatively, if statements without else parts are
convenient. We made sure that implementations are free to perform sanity
checks by declaring it a mistake to use the result of an if that doesn't
have an else part (when the test evaluates false; I think that restriction
was an oversight and will be changed so that it is always a mistake to use
the result of such an if).
2. The use of "block" rather than "begin" conflicts with standard
programming language terminology dating back to the Algol 60 report.
In Algol 60, a block necessarily contains declarations at its head.
The "begin" expressions of Scheme correspond to Algol 60 compound
statements, not to Algol 60 blocks, and this has been a significant
source of confusion. (Note that even Pascal blocks, which do not
necessarily contain declarations, are distinct from Pascal compound
At the workshop there was a consensus that "block" had to go. The main
suggestions to replace it were "progn" and "begin", neither of which was
judged particularly wonderful. The argument in favor of "progn" was
tradition; the argument against "progn" was that it was utterly and
irredeemably random. Several votes were taken comparing the various
candidates head to head with other candidates, asking how many people could
live with the various candidates, and so on. "begin" was the winner.
It was at one point remarked that (let() ...) was equivalent to (begin ...)
and required the same number of keystrokes. We took this seriously but
decided to have a special form for it anyway.
3. Many implementations will allow single keys in case expressions, as an
extended feature. Several people wanted the single key idea to be optional
rather than extended, but there were objections and the feature didn't seem
important enough to justify a long discussion. Please remember that complete
unanimity was required to adopt even optional features.
1. "call/cc" is nonsense to the uninitiated, and even
"call-with-current-continuation" is a bit random. As for the number of
keystrokes, most of us felt that it was appropriate to discourage people
from using call-with-current-continuation so often that their fingers
wear out; if there is a common need for it in a program, the programmer
should encapsulate it in his/her own routine, with as short a name as
he/she desires. In short, if you prefer call/cc you can simply say
(define call/cc call-with-current-continuation) and forget about it.
2. Your point about transcendental functions is well taken. There was a
consensus that the transcendental functions should be essential, but two of
us argued the irrelevance of transcendental functions to certain kinds of
systems programming. The wording in the preliminary report was deliberate
-- I wanted to avoid the problem that Common Lisp has, in which the
implementation strategies are dictated in large part by the language
definition. The workshop's decision was worded as you want, however --
"implementations with floats must support" the transcendentals. I don't know
how to say that without talking about implementation strategies, so I said
it the way I said it. I'm very open to suggestions here.
3. I disagree about the length function. It seems that the programmer
almost always knows the type of the object whose length is to be calculated,
so a generic length function doesn't seem that helpful. The real question
is whether everything should be as generic as possible. I think the
workshop participants felt that Common Lisp had gone overboard in the
direction of genericity, and didn't want to follow; once you get started on
genericity it's hard to stop, so we didn't start.
One exception has to do with numbers. The rationale is that the programmer
wants real numbers -- of which the integers are a subset -- but has to
settle for rational numbers. What is an integer but a rational whose
denominator divides the numerator? What is a floating point number but a
rational with the additional information that it probably isn't very
With vectors, strings, and lists, however, the programmer wants the
distinctions, because they are conceptually different data structures.
I suspect that this issue will continue to come up, but my current feeling
is that we're doing it right. Anyone that wants a generic length-of
procedure can write it themselves; if we see a lot of programmers doing
that, we'll move it into the manual, but not before.
I prefer case-sensitive symbols myself, but I have to agree with the position
of the workshop that when case is important the programmer probably should be
using strings instead. I don't follow your argument about Prolog-like
variables at all -- why should they be difficult to implement in Scheme?
In some languages case is important but not in others; all this means is
that you can't use the same lexical analyzer for all languages. Some
people will be implementing Common Lisp on top of Scheme, but there's
little hope that the same parser can be used both for Common Lisp and for
Scheme, let alone for both APL and Scheme.
I had forgotten that some terminals work only with upper case. That
certainly was not a consideration at the workshop.
The string->symbol procedure doesn't change case; the preliminary report did
not say so explicitly, but it should have.