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

Raymond Wiker rwiker at gmail.com
Thu Oct 22 13:21:04 PDT 2009


Why do you think that let necessarily establishes a lexical binding?

On Oct 22, 2009, at 22:04 , Taoufik Dachraoui wrote:

> 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 cannot
>
> > 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
> X
> ? (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  
> init)
>        (+ 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.
>
> Taoufik
>
> 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
>>>
>>
>
> _______________________________________________
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
> http://clozure.com/mailman/listinfo/openmcl-devel

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


More information about the Openmcl-devel mailing list