[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: critique of preliminary report



I am posting this in response to Kent Pitman's excellent critique
of the preliminary report on the October workshop.


ERRORS AND OVERSIGHTS

I should have said:

Numbers, strings, characters, and #!TRUE and #!FALSE are
self-evaluating, which means they need not be quoted. Symbols and
pairs are not self-evaluating.  It is not specified whether other
things are self-evaluating.

The semantics of (BEGIN) is not specified.

TRUNCATE could be defined by

    (DEFINE TRUNCATE
      (LAMBDA (X)
        (IF (NEGATIVE? X)
	    (- 0 (FLOOR (ABS X)))
	    (FLOOR X))))

VECTOR-REF takes a vector v and an nonnegative integer n such
that n < (VECTOR-LENGTH v) and returns ... .

----------------------------------------------------------------

WHAT DOES "OPTIONAL" MEAN?

The intent of the workshop was that extensions must not conflict
with optional features, and I should have said so.  In fact some
features were made optional in order to prevent dialects from
using certain syntaxes for other purposes.  It follows that #b,
#o, #d, #x, #\, and so on can't be used for any purpose other
than to support the optional feature.

I agree that the "optional" stuff about NIL and T is ridiculous.
What I should have said instead is that implementations that want
to treat NIL and T as constants can do so.  In effect this is a
warning against using NIL and T to name variables.  Note that
(FOO . NIL) cannot read the same as (FOO) no matter what.

I didn't mean to say that "optional" names or features are to be
preferred to essential names or features, and I don't think I did.

----------------------------------------------------------------

POOR WRITING IN THE PRELIMINARY REPORT

I agree with Kent Pitman's points regarding the use of "...",
"mistake", "respectively", and "double quote".

I agree that the set of single character tokens needs to be
better defined.  I would like to include appendixes in the final
report with more rigorous descriptions of the lexical syntax, the
context-free syntax, and the denotational semantics of Scheme.

How about "The order of evaluation within a procedure call is not
specified"?  That isn't quite true, of course -- normal order
evaluation is prohibited.

I should have said that some single object represents both false
and the empty list.  There may be other objects representing
false.  Might there be other objects representing the empty list?
(I hope not.)

I agree that it would be better to have said that (NUMBER? x)
doesn't imply (INTEGER? x).

I hope everyone noticed that it is an error to take the CAR or
CDR of the empty list.

The definition of a proper list in the preliminary manual was a
joke.  The notion of a proper list has to do with finiteness,
which is not first order definable.

----------------------------------------------------------------

LEXICAL MATTERS

It is not specified whether single quote, backquote, sharp sign,
and vertical bar are delimiters that terminate symbols.  The
status of these characters would be decided by a general rule
that emerged during discussion at the workshop, but not everyone
agreed to the general rule.  The general rule is:  Special
characters that come in pairs (left and right parenthesis, left
and right bracket, left and right curly brace, doublequote)
should be delimiters while other special characters (period and
so on) should be preceded by a space if they are to be used in
their special sense.  Semicolon isn't really an exception to the
pattern because the end of line would be a delimiter anyway.
Whether vertical bar should be a delimiter according to the rule
depends on whether vertical bar is a special character that comes
in pairs, which is not specified.  According to the rule single
quote, backquote, and sharp sign should not be delimiters.

> * I agree with reserving {, [, ], and }, but I would specify that they
>   may be used as alphabetic according to syntactic escape conventions.

I don't understand "...according to syntactic escape conventions".

I have yet to hear of a good use for slashification of symbols.
If there is no compelling need for a feature, we should leave it
out.  The workshop allowed slashification but did not encourage
it.

> * I notice that the space of symbol names is highly constrained for
>   the "required subset". A property, however, that should be required
>   is that within any given dialect, every interned symbol (no matter what
>   characters it contains) must have a printed representation which is
>   read-invertable within that dialect. I suspect that all dialects 
>   do this already anyway, but it should be a guaranteed property of the
>   language since programmers will tend to depend on such things and should
>   have a guaranteed semantics backing them up.

We probably ought to require something along these lines, but the
property you desire is too strong.  It is enough that every
symbol read by the reader be printed in a form that will read
back in as the same symbol.  Other symbols are too random to
worry about.  In fact, I would be satisfied if only the required
set of symbol names have the property you desire.  For what it's
worth, Franz Lisp does not have the property, but I doubt that
its lack is a significant cause of dissatisfaction with Franz
Lisp.

----------------------------------------------------------------

SPECIAL FORMS

LETREC vs LABELS, REC vs LABEL, and SET vs SET! are matters of
taste that needed to be decided one way or the other, and were.
History plays a significant role in decisions such as these.  The
first two matters had history on both sides, but the history of
SET in traditional Lisp counts against it.

In some cases the IF, COND, and CASE special forms return
unspecified values.  The SET!, DEFINE, and DEFINE! special forms,
and the SET-CAR!, SET-CDR!, and VECTOR-SET! procedures, always
return unspecified values.  Except for the result of the DEFINE
form, I wrote that it is a "mistake" to use these undefined
values, and except for the results of the DEFINE and DEFINE!
forms I wrote that implementations could signal an error if the
values that were returned were "used".  What I wrote is faithful
to the workshop's decisions, but I can be accused of deviating in
the cases of DEFINE and DEFINE! .

Kent is right to question what we meant by "using" a value.  The
answer is that we don't know.  Obviously an implementation could
return a strange value that would cause an error to be signalled
if an attempt were ever made to take its CAR or its successor; an
implementation could also arrange for an error to be signalled if
the value were ever an operand to EQ? or CONS; and there are no
doubt other things that an implementation could do as well.  I
will not offer a formal description of the circumstances under
which an error could be signalled, because I want to leave room
for implementations to experiment with different approaches.

A DEFINE form is at "top level" iff it it not nested within any
other form.  This definition clearly establishes circumstances
that do not count as top level, but it does not establish any
circumstances that do count as top level.  I think each
implementation will have to specify circumstances under which a
DEFINE form has the described semantics, and those circumstances
would then count as top level for that implementation.

The Abelson and Sussman book uses DEFINE inside LAMBDA as
syntactic sugar.  Scheme's future is tied to the success of that
book, so the sugar was dignified with "optional" status.  The
optional status of the sugar required that ordinary DEFINE be
restricted to "top level".

The (DEFINE (fn . args) . body) sugar was dignified with
"optional" status for the same reason.  Kent has acquired a taste
for this sugar, but I consider it a violation of orthogonality
that is doubly pernicious:  (1) it discourages programmers from
thinking of procedures as objects distinct from their names; (2)
it discourages programmers from using procedures with local
state.

I agree that the optional status of named LET should imply an
optional status for named LET*, or else both named LET and named
LET* should be left out altogether.  By the way, David Bartley
asks whether the body of a named let is within the scope of the
name.  The Revised Report has the body within the scope of the
name.  Does anyone want to argue that the body should be outside
the scope of the name?

When it was asked if DO should bind RETURN, someone said "Of
course not!", and that was the end of the discussion.  If DO were
to bind RETURN I believe that DO would be the only construct in
even the optional language to bind an identifier that does not
appear explicitly in the code, and I see no reason to condone
that kind of anomaly.

----------------------------------------------------------------

DATATYPES

I was disappointed that we were unable to agree that any
datatypes were disjoint.  The fact that the workshop participants
insisted on a special note to the effect that characters need not
be a distinguishable data type leads me to believe that despite
their votes most participants assumed that other data types were
distinguishable.  In the final report I intend to recommend that
at the very least numbers, symbols, and pairs should be disjoint;
does anyone object?

Even without disjointness of data types, the NUMBER? and INTEGER?
predicates are useful because they define the domains of other
procedures.  Thus if all strings are numbers then it must be
possible to subtract strings.

The nonsense to the effect that pairs might be indistinguishable
from vectors of length 2 is to remind folks not to assume that
pairs and vectors are disjoint.  I agree that the note is out of
place and ugly.

I expect streams will be a Scheme data type, but as Kent points
out they might overlap with (say) numbers.  Nonetheless the
STREAM? predicate will be useful because anything of which the
STREAM? predicate is true will have to support the operations on
streams.

----------------------------------------------------------------

PROCEDURES

I think it went without saying that escape procedures can be
called more than once.  We didn't feel any need to say that the
addition procedure could be called more than once, either.

The generalizations of +, -, *, and / to arbitrary arity must
follow Common Lisp, so the ambiguity is not great.  There is some
ambiguity, however, because Common Lisp has all sorts of rules
about integers, rationals, floats, and complexes that don't apply
to Scheme.

MIN and MAX are restricted from arity 0 because some
implementations don't have a smallest or largest representable
number.

Implementations should not be allowed to signal an error on
something like (=? 1 1.0).  I don't think we should specify that
the result is true because you might want to implement a Scheme
in which "approximations" are a subtype of the numbers, in which
1.0 is read in as an approximation, and in which all equality
comparisons involving approximate numbers return false.

(If you haven't caught on by now, I'm perfectly comfortable with
the fact that Scheme is far less tightly specified than Common
Lisp.  I believe Scheme can continue to represent the future of
Lisp only by being open to experimentation.)

I would rather not talk about "interning" a symbol, because
there is no need to talk about it when all symbols are interned.
I have to use words like "interned" to talk about implementations
in which not all symbols are interned, but for definitions I
would like to refer people to manuals for traditional Lisps.

LENGTH is defined on proper lists, and its action on anything
else is not specified.

I can't imagine a definition of APPEND! that would want to mutate
its last argument either.  Shall we say it doesn't?

Kent's suggestions for MEMQ?, MEMV?, MEMBER?, ASSQ?, ASSV?, and
ASSOC? are interesting.  Several people at the workshop, notably
Hal Abelson, expressed the belief that we ought to reconsider the
entire MEMBER/ASSOC complex of procedures.

MAPCAR and MAPC have their historical names for historical
reasons, and I would not be averse to renaming them eventually.
If MAPCAR is defined as follows in an implementation that
evaluates right to left, then the list of results is constructed
from right to left:

	(DEFINE MAPCAR
	  (LAMBDA (F L)
	    (IF (NULL? L)
	        '()
		(CONS (F (CAR L)) (MAPCAR F (CDR L))))))

I agree with Kent that the result of VECTOR->LIST cannot
reasonably be guaranteed to be a new object.

VECTOR-SET!, SET-CAR!, and SET-CDR! seem inconsistent to me too.
I think we should offer a prize for the best rationalization of
these names.

I think garbage collection should be treated as an issue of
performance rather than as an issue of semantics.

				Peace, William Clinger