From: Jeff Lipton
Subject: Ambiguity about SPECIAL declarations
Date: 
Message-ID: <54g7ef$ee3@panix2.panix.com>
I am confused about the scope of SPECIAL declarations in the
LET* special form. My understanding is that the ANSI standard
is that special declarations do not take effect until after
initialization forms are evaluated. Thus the interpretation of
the following is unclear:

		in the LET* initializations below, should the
form (* a1 17) refer to the just bound value of a1 (13) or to
the lexically bound value of 1? GCL seems to use the former
interpretation.

(let ((a1 1) (a2 2))
  (declare (special a1) (special a2))
  (format t "1. a1, a2: ~s,~s~%" a1 a2)
  (let  ((a1 (* a1 10)) (a2 (* a2 10)))
    (format t "2. a1, a2: ~s,~s~%" a1 a2)
    (let* ((a1 (+ a1 3)) (a2 (* a1 17))) ; special binding ?lexical reference
      (declare (special a1) (special a2))
      (format t "3. a1, a2: ~s,~s~%" a1 a2))))





Thank You!

-- 
+----------------------------------------------------------------------------+
| Jeffrey F. Lipton, M.D. (···@panix.com) |   (212)-663-9333 (home)          |
| 8 W. 95th St., #3  NY, NY 10025         | Fundamentalist: One with whom    |
+-WWW: http://www.panix.com/~jfl -----there is something fundamentally wrong.|
From: Howard R. Stearns
Subject: Re: Ambiguity about SPECIAL declarations
Date: 
Message-ID: <326BE939.7566F4CF@elwoodcorp.com>
Jeff Lipton wrote:
> 
> I am confused about the scope of SPECIAL declarations in the
> LET* special form. My understanding is that the ANSI standard
> is that special declarations do not take effect until after
> initialization forms are evaluated. Thus the interpretation of
> the following is unclear:
> 
>                 in the LET* initializations below, should the
> form (* a1 17) refer to the just bound value of a1 (13) or to
> the lexically bound value of 1? GCL seems to use the former
> interpretation.
> 
> (let ((a1 1) (a2 2))
>   (declare (special a1) (special a2))
>   (format t "1. a1, a2: ~s,~s~%" a1 a2)
>   (let  ((a1 (* a1 10)) (a2 (* a2 10)))
>     (format t "2. a1, a2: ~s,~s~%" a1 a2)
>     (let* ((a1 (+ a1 3)) (a2 (* a1 17))) ; special binding ?lexical reference
>       (declare (special a1) (special a2))
>       (format t "3. a1, a2: ~s,~s~%" a1 a2))))
> 
> Thank You!
> 
> --
> +----------------------------------------------------------------------------+
> | Jeffrey F. Lipton, M.D. (···@panix.com) |   (212)-663-9333 (home)          |
> | 8 W. 95th St., #3  NY, NY 10025         | Fundamentalist: One with whom    |
> +-WWW: http://www.panix.com/~jfl -----there is something
> fundamentally wrong.|

Short answer (IMHO):

1. The initform for the last binding of A2 should definiately refer to
the just bound binding of A1.  This is because you used LET* rather
than LET, and has nothing to do with whether this last binding of A1
is special.  (All the implementations I tried agree.)

2. You are correct in that the special declaration should not apply to
the init forms, so the last init form for the last (special) binding
of A1 should use the current lexical value of A1 (10) to produce
A1=13.  (CMUCL, GCL, and ECL agree. CLISP and Allegro do not, and I
think they are wrong.)

Long answer:

The spec says that "The scope of a bound declaration is the same as
the lexical scope of the binding to which it applies; for special
variables, this means the scope that the binding would have had had it
been a lexical binding."

To me, this unequivocally means that the last binding of a2 will have
a value of 221 (i.e. (* 13 17), because a1 refers to the just recently
bound variable a1, which has a value of 13).  In other words, in this
case, the special declarations have no impact. 

It also means that the last binding of a1 will have a value of 13
because A1 in the initform (+ a1 3) refers to the lexically enclosing
binding of a1, which happens to be 10.


Your question raises some interesting issues, however, that are not
completely clear to me:

I. SCOPE OF DECLARATIONS WHICH APPLY TO LOCALLY DECLARED SPECIALS

Is the above quote also true for FREE special declarations. For example:

(setq x 0)			 ; Global binding for x.
(let ((x 1))			 ; First lexical binding for x.
  (print x)			 ; x is 1
  (locally (declare (special x)) ; Does not establish a new binding.
    (print x)			 ; x is 0
    (let ((x 2))		 ; Second lexical binding for x.
       (print x))		 ; x is 2
    (print x))		 	 ; x is 0 (back to global binding)
  (print x))			 ; x is 1 (back to lexical binding)
x				 ; x is 0

In particular, I would like to note that there are precisely three
bindings for x in this example, not four.  There are, therefore, three
scopes for declarations.  In particular, a proclamation established
at top level for the global binding of x also applies when this global
binding is RE-ESTABLISHED by the locally form.

A better test case, then would be one which provided TYPE or some
other declaration for the global binding of X, and tested which cases
enforced the declaration.  Unfortunately, most implementations don't
enforce such declarations, so I guess this is fairly academic.

II. WHEN IS THE OLD SYMBOL-VALUE SAVED WHEN BINDING SPECIAL VARIABLES?

Steele says that "Any program construct that binds a varible
effectively saves the old value of the variable and causes it to have
a new value, and on exit from the construct the old value is
reinstated."

Consider:

(defvar foo 100)
(defvar bar 100)

(let ((foo (setf bar 1))
      (bar 3))
 ...)


It is clear that FOO has the dynamic value 1 at the start of the body
of the LET form, and that after leaving the LET form, the value of FOO
will be restored to 100.

However, what value is restored to BAR when leaving the LET form? Is
it the value BAR had before entering the whole LET (100), or the value
before BAR was bound IN the LET?  The latter occurs conceptually after
all the initforms have been evaluated, so the value in this case would
be 1.

Similarly, in:
(let* ((foo (setf bar 1))
       (bar 3))
 ...)

Will BAR be restored with the value from before the entire binding
construct was entered (100) or from before the specific binding was
made (1)?

In my opinion, the value restored is the value before binding, so in
both these cases, the value restored to BAR should be 1.  (All the
implementations I tried agree.)