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

Taoufik Dachraoui taoufik.dachraoui at wanadoo.fr
Thu Oct 22 12:27:49 PDT 2009


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
>






More information about the Openmcl-devel mailing list