[Openmcl-devel] process-run-function and "dynamic vs lexical"
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
> ? (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
> ; a new lexical variable binding (not special unless
> declared so)
> Only because a symbol is implicitly declared special within a let
> 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)
>> ?(let ((x 1))
>> (flet ((foo () x))
>> (let ((x 5)) (+ x (foo)))))
>> 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)
>> ? (let ((x 1))
>> (flet ((foo () x))
>> (let ((x 5)) (+ x (foo)))))
>> 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
>> 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
>> 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
>> 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).
>> 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.
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Openmcl-devel