[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.


Lambda Syntax

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.
For example,
     (case x ((a) ...) ((b) ...) ((c d) ...) (else ...))
would simply be
     (case x (a ...) (b ...) ((c d) ...) (else ...)).


Functions

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 
a line?

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.


Lexical Matters

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.