[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Comments on the Preliminary Report (2 pages)
Comments on Essential Scheme
These comments are arranged in four categories: lambda syntax, other
special forms, functions, and lexical matters. I feel quite strongly
about the issues I outline here. I have other minor gripes (don't we
all) that I didn't bother to include here, for fear they would water
down the substantive issues.
For several years my Scheme system has had a syntax for lambda
expressions that allows naming of the closure within the body of the
closure for enhanced readability and efficiency. The syntax is:
(lambda name formals . body)
where name is a symbol bound lexically to the closure within body,
formals is a list of formal parameters, and body is a set of zero or
more forms to execute. Name may be omitted and there is no ambiguity
since formals is always a list.
This feature, which I have called "named lambda," allows terse,
referentially transparent recursive function definitions. It is similar
to the optional "rec," special form, but is shorter and perhaps more
easily optimized than rec. It is quite a bit shorter than using
"letrec." For example, the boring factorial function looks like:
(lambda fact (x) (if (= x 0) 1 (* x (fact (- x 1))))),
a totally self contained definition.
Named lambda generalizes to named let, something which seems to have
appeared elsewhere independently. It looks like:
(let name ((x1 v1) (x2 v2) ...) . body),
where name may again be omitted. It translates into:
((lambda name (x1 x2 ...) . body) v1 v2 ...),
and replaces the old iterate expression.
Unfortunately, the partial destructuring provided by the adopted lambda
syntax conflicts with the named lambda syntax, introducing an ambiguity
in some cases, as in:
(lambda f (g x) ...).
Is this a named lambda with two formals or an unnamed lambda with a
single &rest formal?
The partial destructuring syntax is merely a different syntax for the
&rest formal parameter adopted by Common Lisp. The only benefit to be
gained by not using the Common Lisp syntax is that some implementations
might generalize to full destructuring. I think it more likely that we
would want to generalize to optional arguments. Why not just use part
of the syntax adopted by Common Lisp? For now, we could make the &rest
syntax required and the &optional syntax optional.
If everyone dislikes the &rest syntax then I think we ought to resolve
the ambiguity with named lambda by requiring the name to be present.
This would improve code readability and facilitate optimization
regardless of the system the code is executed on.
Other Special Forms
1. The "if" special form should require an else part. This allows the
compiler/interpreter to make a sanity check for the user which might
save some grief, and seems a little cleaner. The macros "when" and
"unless" are the appropriate way to express the intended meaning.
2. Block is a much better name for the statement grouping special form
than "begin". Do we really need an artifact of Algol syntax in our
language? After all, it is a block of code, not a begin of code.
(If someone is worried about clashing with a process blocking function
they should name their function "block-process.")
3. Case expressions should allow single keys without putting them in a
list. The user rarely wants the single key to be a list (eq semantics
and all), so there really isn't any ambiguity. Since single keys are
probably the most common, case expressions will be less bulky.
(case x ((a) ...) ((b) ...) ((c d) ...) (else ...))
would simply be
(case x (a ...) (b ...) ((c d) ...) (else ...)).
1. Call/cc should be an alternative to call-with-current-continuation.
How are we ever going to get people to feel comfortable with something
so imposing that it requires 30 keystrokes to type in and takes up half
2. Transcendental functions should be required only in implementations
with floating point numbers, not just any implementation with numbers
other than integers. In particular, an implementation with rational or
interval arithmetic should not be bound to supporting transcendental
functions. (This was probably just a misstatement in Will's note.)
3. The length function should be generic, returning a value for all
reasonable arguments. There can still be individual functions list-
length, string-length, vector-length, and so on.
Scheme systems should be case sensitive. Let's not forget that symbols
have other uses than as Scheme identifiers. How can we implement
prolog-like variables in Scheme without being able to differentiate
between upper and lower case letters within the symbols? Does anyone
really still use an upper-case only terminal? Assuming case
sensitivity, all standard Scheme functions and special forms should be
written with entirely lower-case letters.