[Openmcl-devel] process-run-function and "dynamic vs lexical"

Taoufik Dachraoui taoufik.dachraoui at wanadoo.fr
Thu Oct 22 13:04:22 PDT 2009

I would like to add the following:

SPECIAL as defined in the specs:

"Specifies that all of the vars named are dynamic"

So if a variable is defined in a let block it is a lexical binding and  

 > ccl
? (let ((h 1))  ; there is no defvar for h
     (declare (special h))
     (let ((h 2))
       (+ h (locally (declare (special h)) h))))
3   ; here the programmer controls everything, decides what is special  
and what is not

? (defvar x 1) ; x is special
? (let ((x 1))       ; without declaring x special it is special  
because of defvar (lost control)
      (let ((x 2))    ; so where in the specs that says (defvar name  
        (+ x x)))     ; must treat name as special everywhere even if  
it is
4      	    	     ; used in a let block, where let is supposed to create
	             ; a new lexical variable binding (not special unless  
declared so)

Only because a symbol is implicitly declared special within a let block
when defvar'ed that we may be in trouble with our code as we saw in  
many examples.

Again look at this example of a closure:

(let ((x 1)) (defun foo (y) (+ x y)))

It is obvious that if x is defvar'ed then the code will not behave as  
the programmer
intention. This closure definition is legitimate, but the programmer  
can use a symbol
name that is defvar'ed without him knowing.

Again, a symbol is special only when you declared so using defvar or  
(declare (special ..))
and that when let is used it creates a NEW  variable binding and it is  
not special unless
declared so.


On Oct 22, 2009, at 9:27 PM, Taoufik Dachraoui wrote:

> Ok let me be more methodic
> 1. how do you recognize if a binding is lexical (dynamic)
> >ccl
> ?(let ((x 1))
>    (flet ((foo () x))
>       (let ((x 5)) (+ x (foo)))))
> 6
> ?
> ok the first x is lexical thus the x in foo was replaced by the value
> of x at the time of definition/eval/compile.
> ? (defvar x 2)
> X
> ? (let ((x 1))
>    (flet ((foo ()  x))
>       (let ((x 5)) (+ x (foo)))))
> 10
> ?
> Ok here the first x is dynamic (see below for comments about this)  
> thus the x in
> foo was replaced by <get last value of x at runtime> and it is 5  
> when foo is
> executed.
> So now I hope it is clear what is lexical and what is dynamic.
> The interesting stuff is the second scenario.
> After defining x using defvar, the let block do not follow the  
> specs; in the specs,
> let creates a new variable binding and that binding is lexical  
> unless the name
> is declared special.
> Now my question, how come at compile/eval time the foo function was  
> not
> lexically bound to the first  value of x within the let block (since  
> x is the name
> of a new variable binding and it is lexical since there is no  
> special declaration
> for x?).
> Ok you will say, because x is defined,at toplevel, using DEFVAR. Ok  
> fair enough,
> that is how it is implemented; but don't you see that there is a  
> clash between how
> the specs defines the let block and how it behaves in the presence  
> of a globally
> defined dynamic variable?
> I believe that the way dynamic variables are implemented is the  
> reason for many bugs
> as said many times in this thread (and among others that is why some  
> prefer the setf
> at toplevel in ccl versus the setf as defined by cmucl).
> I bilieve that any new variable bound within a let block must shadow  
> dynamic variables
> with the same name defined at higher levels; special declarations make
> sense in this context; it is the only way for you to be able to use  
> a shadowed dynamic
> variable within a let block:
> ? (defvar x 1)
> ? (let ((x 3))
>    (+ x (locally (declare (special x)) x)))    ; not important how  
> to specify to the compiler
> 4										; which x to use (lexical or dynamic)
> This view of how lexical and dynamic variables makes things simpler  
> and easier to
> understand, because if something is lexically bound it is not  
> dynamic in its scope
> (unless so desired by the programmer using declaring it special).
> Dynamic variables sould not be pervasive (unwelcome) but should be  
> used with some
> confidence by all programmer and not only experts should use them;  
> For this they need
> to be easy to understand and intuitive (no surprises only when there  
> is an obvious error
> in the program).
> Taoufik
> On Oct 22, 2009, at 8:20 PM, John McAleely wrote:
>>> let creates new variable binding for the names x and y and these
>>> bindings are lexical unless they are declared special.
>> OK. I think this is where the mistake in your reasoning occurs,  
>> since you appeal only to the CL spec.
>> My understanding is that the closure you create will bind x and y  
>> in the thread it executes in.
>> When you jump into another thread via process-run-function, the  
>> lexical binding created by your let is no longer visible.
>> My further understanding is that the CL spec does not define this  
>> multi-threaded behaviour, and that implementation conventions in  
>> this area tend to appeal back to implementations on the Lisp  
>> Machine that proved convenient.
>> So your attempt to understand the behaviour of process-run-function  
>> only by appeal to the CL spec is where you have made the mistake in  
>> your reasoning.
>> J

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.clozure.com/pipermail/openmcl-devel/attachments/20091022/cc74c1b8/attachment.htm>

More information about the Openmcl-devel mailing list