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

DECLARE SPECIAL Considered Confusing

    Date: 20 Jul 1986 18:52-EDT
    From: NGALL at G.BBN.COM
        Date: Sun, 20 Jul 86 17:11:53 EDT
        From: Alan Bawden <ALAN at AI>
	The old rule ... did have the advantage that you can always extract
	the declarations from the body of a macro form and just wrap the
	entire expansion in a LOCALLY.

    (let* ((x 1) (y (1+ x))) (declare (special x)) ...)
    is not equivalent to
    (locally (declare (special x))
      (let ((x 1))
        (let ((y (1+ x)))

You're quite right.  I had always assumed that the ability to extract
declarations like this was the reason we adopted the rule in the first
place (making both macros and documentation easier to write), but I was
certainly mistaken.

Actually, the more I think about this as a simplification, the more I like
it.  So here is a counter-proposal for rationalizing the semantics of

1.  All declarations are completely pervasive.  That is, if you write

  (locally (declare (special foo)) ...)

then every occurance of FOO within the body is taken to be a special
reference or a special binding.  The only way to escape from the effects of
a declaration within the body, is to explicitly shadow the declaration with
another.  This applies to -all- declarations: FTYPE, INLINE, etc.

2.  Declarations that occur in the bodies of special forms (DEFUN, LET, DO,
etc.), and in LAMBDA expressions, are taken to mean the same thing as if
the entire form was enclosed in a LOCALLY containing the same declarations.

  (let ,pairs ,@dcls ,@body)


  (locally ,@dcls (let ,pairs ,@body))

are completely equivalent.  

(Since LAMBDA expressions aren't forms, the equivalent using LOCALLY isn't
always completely straightforward to construct.  For example, this case:

  ((lambda ,vars ,@dcls ,@body) ,@vals)

is equivalent to using LOCALLY as follows:

  (funcall (locally ,@dcls (function (lambda ,vars ,@body))) ,@vals)


Question:  Why isn't LOCALLY just called PROGN?