From: Juanjo
Subject: Scope of declaration
Date: 
Message-ID: <1145212868.378426.169780@v46g2000cwv.googlegroups.com>
What is the following supposed to produce?

(defun foo (y)
  (flet (( faa (&key (x y))
    (declare (special y))
    x))
   (let ((y 4))
     (declare (special y))
     (faa))))

(foo 3)

I would suspect that the answer is 3, because the first special
declaration does not apply to the initialization form of X. This is
what the lisp interpreter in ECL gives, and also CLISP. However both
the C compiler from ECL and my copy of CMUCL (I think it is 19c)
produce 4.

Help is welcome.

Juanjo

From: Juho Snellman
Subject: Re: Scope of declaration
Date: 
Message-ID: <slrne4587m.j0p.jsnell@sbz-30.cs.Helsinki.FI>
Juanjo <·····················@googlemail.com> wrote:
> What is the following supposed to produce?
> 
> (defun foo (y)
>   (flet (( faa (&key (x y))
>     (declare (special y))
>     x))
>    (let ((y 4))
>      (declare (special y))
>      (faa))))
> 
> (foo 3)
> 
> I would suspect that the answer is 3, because the first special
> declaration does not apply to the initialization form of X.
[...]

I believe that's the right interpretation.

-- 
Juho Snellman
From: Pascal Costanza
Subject: Re: Scope of declaration
Date: 
Message-ID: <4afmgpFt50qpU1@individual.net>
Juanjo wrote:
> What is the following supposed to produce?
> 
> (defun foo (y)
>   (flet (( faa (&key (x y))
>     (declare (special y))
>     x))
>    (let ((y 4))
>      (declare (special y))
>      (faa))))
> 
> (foo 3)
> 
> I would suspect that the answer is 3, because the first special
> declaration does not apply to the initialization form of X. This is
> what the lisp interpreter in ECL gives, and also CLISP. However both
> the C compiler from ECL and my copy of CMUCL (I think it is 19c)
> produce 4.
> 
> Help is welcome.

3.3.4 of the HyperSpec states the following: "A declaration that appears 
at the head of a binding form and applies to a variable or function 
binding made by that form is called a bound declaration [...]"

The (flet ((faa ...)) ...) form in your example does not provide a 
binding for y, so the special declaration is not a bound declaration.

Furthermore: "Declarations that are not bound declarations are called 
free declarations."

So the (declare (special y)) form inside the faa definition is a free 
declaration.

Furthermore: "Unless explicitly stated otherwise, the scope of a free 
declaration includes only the body subforms of the form at whose head it 
appears, and no other subforms. The scope of free declarations 
specifically does not include initialization forms for bindings 
established by the form containing the declarations."

So the result should be 3, since the y in the lambda list for faa is an 
initialization form for x.

Finally, the section on special declarations does not contain any 
redefinition of what scopes it may affect.


Pascal

-- 
3rd European Lisp Workshop
July 3-4 - Nantes, France - co-located with ECOOP 2006
http://lisp-ecoop06.bknr.net/
From: Harald Hanche-Olsen
Subject: Re: Scope of declaration
Date: 
Message-ID: <pcolku5qnoe.fsf@shuttle.math.ntnu.no>
+ Pascal Costanza <··@p-cos.net>:

| Furthermore: "Unless explicitly stated otherwise, the scope of a free
| declaration includes only the body subforms of the form at whose head
| it appears, and no other subforms.

Ah.  I looked at the same sentence, but somehow missed the word
"body".  I suppose an initialization form is a subform, but not a BODY
subform.  That settles the nagging doubt I left in my other post.

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- It is undesirable to believe a proposition
  when there is no ground whatsoever for supposing it is true.
  -- Bertrand Russell
From: Harald Hanche-Olsen
Subject: Re: Scope of declaration
Date: 
Message-ID: <pcopsjhqnv1.fsf@shuttle.math.ntnu.no>
+ "Juanjo" <·····················@googlemail.com>:

| What is the following supposed to produce?
|
| (defun foo (y)
|   (flet (( faa (&key (x y))
|     (declare (special y)) ; [*]
|     x))
|    (let ((y 4))
|      (declare (special y))
|      (faa))))

Hmm.  The declaration that I marked [*] above is a free declaration,
according to paragraphs 2-3 of CLHS 3.3.4:

  A declaration that appears at the head of a binding form and applies
  to a variable or function binding made by that form is called a
  bound declaration; such a declaration affects both the binding and
  any references within the scope of the declaration.

  Declarations that are not bound declarations are called free declarations.

The text goes on to say

  A free declaration in a form F1 that applies to a binding for a name
  N established by some form F2 of which F1 is a subform affects only
  references to N within F1; it does not to apply to other references
  to N outside of F1, nor does it affect the manner in which the
  binding of N by F2 is established.

So the question boils down to:  Is the reference to Y in the lambda
list of FAA inside, or outside

This example in 3.3.4.1 is similar:

   (lambda (&optional (x (foo 1))) ;[1]
     (declare (notinline foo))     ;[2]
     (foo x))                      ;[3]

  the call to foo in the first line might be compiled inline even
  though the call to foo in the third line must not be. This is
  because the notinline declaration for foo in the second line applies
  only to the body on the third line.

Based on this example, I would think that analogously the scope of the
declaration in [*] does not include the init-form Y, so

| (foo 3)

should return 3.  But I have a hard time pinning it down in the CLHS,
other than by that example.

| I would suspect that the answer is 3, because the first special
| declaration does not apply to the initialization form of X. This is
| what the lisp interpreter in ECL gives, and also CLISP. However both
| the C compiler from ECL and my copy of CMUCL (I think it is 19c)
| produce 4.

But SBCL says 3.

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- It is undesirable to believe a proposition
  when there is no ground whatsoever for supposing it is true.
  -- Bertrand Russell
From: David Sletten
Subject: Re: Scope of declaration
Date: 
Message-ID: <3Az0g.4302$543.2034@tornado.socal.rr.com>
Juanjo wrote:

> What is the following supposed to produce?
> 
> (defun foo (y)
>   (flet (( faa (&key (x y))
>     (declare (special y))
>     x))
>    (let ((y 4))
>      (declare (special y))
>      (faa))))
> 
> (foo 3)
> 
> I would suspect that the answer is 3, because the first special
> declaration does not apply to the initialization form of X. This is
> what the lisp interpreter in ECL gives, and also CLISP. However both
> the C compiler from ECL and my copy of CMUCL (I think it is 19c)
> produce 4.
> 
> Help is welcome.
> 
> Juanjo
> 

The FLET form creates a closure over FOO's parameter Y:
CL-USER(27): (defun foo (y) 

   (flet (( faa (&key (x y))                             ;Y refers to 
FOO's parameter
     (declare (special y)) ;Free declaration doesn't affect preceding 
initialization
     x)) 

    (let ((y 4)) 

      (declare (special y)) 

      #'faa)))
FOO
CL-USER(28): (defvar *f1* (foo 1))
*F1*
CL-USER(29): (defvar *f2* (foo 2))
*F2*
CL-USER(30): (funcall *f1*)
1
CL-USER(31): (funcall *f1* :x 9)
9
CL-USER(32): (funcall *f2*)
2
CL-USER(33): (funcall *f1*)
1

Aloha,
David Sletten