From: Xenos
Subject: Re: dynamic scoping
Date: 
Message-ID: <yX759.101617$8M1.21001710@twister.nyroc.rr.com>
> Remember, this text is for newbies who don't know anything about Lisp.
> That explanation is roughtly correct, in the absence of dynamic rebinding,
> which saves and restores the value. I cringed a little when I read that;
> some newbie might walk away thinking that Lisp borrows ideas from BASIC.
>
As I am a newbie when it comes to Lisp.  I have programmed professionally
for years and in several languages, but all were imperative.  If by "roughly
correct" you mean they have a similar end result, I see your point.  I still
prefer to understand the mechanicism that underlay the languages features I
choose to use in a program.

> In the absence of multithreading support, there is still only one instance
of a
> special variable, only that value is saved and restored by the
establishment
> and disestablishment of a dynamic binding. You can save and restore the
> value of a global variable in just about any language, including assembly
> languages. In fact, saving and restoring machine registers to and from
> the stack is an example of this.
>
As I stated above I am a newbie to Lisp, so I can't speak for it.  But you
don't need more than one thread of execution for there to be multiple
objects with the same name existing on the call stack (as I tried to show in
my example)..  The point of which, when this happens, global variables and
dynamically bound one don't even act logically the same (as I assumed was
your first point above).    Either way, multiple threads mean multiple
stacks, so two objects of the same name created by two different tasks would
still be uniquely disambiguated

Unless you are taking at the machine level, saving and restoring a global
doesn't make any sense.  A global exists in its own place in statically
allocated memory, not the stack or heap.  It is always accessible, and to
everyone.   It may need to be saved/restored in registered when used by the
processor but that is a concern of the compiler.

> That is only an illusion, which is a consequence of saving and restoring
the
> value. Saving and restoring the value allows the accesses to always go to
> the same 'a' object, simplifying the implementation. The stack holds only
> anonymous saved copies which are restored during unwinding.

I'm not sure what exactly you are calling an illusion.  I don't know the
internals of Lisp, but I was speaking mechanically not functionally.


Regards,

Rich
From: Kaz Kylheku
Subject: Re: dynamic scoping
Date: 
Message-ID: <aj6bq5$eap$1@luna.vcn.bc.ca>
In article <·························@twister.nyroc.rr.com>, Xenos wrote:
>> Remember, this text is for newbies who don't know anything about Lisp.
>> That explanation is roughtly correct, in the absence of dynamic rebinding,
>> which saves and restores the value. I cringed a little when I read that;
>> some newbie might walk away thinking that Lisp borrows ideas from BASIC.
>>
> As I am a newbie when it comes to Lisp.  I have programmed professionally
> for years and in several languages, but all were imperative.  If by "roughly
> correct" you mean they have a similar end result, I see your point.  I still
> prefer to understand the mechanicism that underlay the languages features I
> choose to use in a program.
> 
>> In the absence of multithreading support, there is still only one instance
> of a
>> special variable, only that value is saved and restored by the
> establishment
>> and disestablishment of a dynamic binding. You can save and restore the
>> value of a global variable in just about any language, including assembly
>> languages. In fact, saving and restoring machine registers to and from
>> the stack is an example of this.
>>
> As I stated above I am a newbie to Lisp, so I can't speak for it.  But you
> don't need more than one thread of execution for there to be multiple
> objects with the same name existing on the call stack (as I tried to show in
> my example)..  The point of which, when this happens, global variables and
> dynamically bound one don't even act logically the same (as I assumed was
> your first point above).    Either way, multiple threads mean multiple
> stacks, so two objects of the same name created by two different tasks would
> still be uniquely disambiguated

But another way to disambiguate is to have a thread-specific lookup
mechanism. For example, (symbol-value ...) can access a thread-specific
value cell. A Lisp implementation based on POSIX threads might use the
functions pthread_getspecific and pthread_setspecific for this.

> Unless you are taking at the machine level, saving and restoring a global
> doesn't make any sense.

In Lisp, the saving and restoring of a special variable is explicitly requested
by the programmer, using a binding construct. So it is far above the machine
level. What this does is save the prior value of the variable, or else the fact
that it has no binding, and binds it to the specified value or NIL. Then some
forms are evaluated. When the let block terminates, the prior status of the
symbol value is restored; either the prior value, or the state of having no
value.

This gives rise to the the illusion that you are creating a new variable which
dynamically captures references to that symbol's value, in effect forcing the
accesses to the closest dynamically enclosed one.

> A global exists in its own place in statically
> allocated memory, not the stack or heap. 

Right; and in the case of a special variable, it exists in the symbol's
value cell which can be explicitly accessed using the (symbol-value ...)
function:

  (defvar *x*)	;; no binding

  (symbol-value '*x*) ==> error, not bound

  (let ((*x* 2)) ;; saves old state
    (symbol-value '*x*)) ==> 2
  ;; old state restored now
  
  (symbol-value '*x*) ==> error, unbound again

When you evaluate a special variable, you are accessing this value.
In other words, for a special variable V,  the expression V
means (symbol-value 'V). The value is a property of the symbol.

> It is always accessible, and to
> everyone.   It may need to be saved/restored in registered when used by the
> processor but that is a concern of the compiler.

Not necessarily so if you are working in assembly language. I only mentioned
assembly language because of the similarity of special variables and the saving
and restoring of registers, which allows the programmer to pretend that there
are more registers, that for instance his function has its own R1 that is
independent from the R1 in the callers. The saving and restoring could be
hidden by some macros, which would in effect let the programmer declare
``give me my own R1 over this block of instructions''.

Of course, for this to be effective, R1 would have to be restored no matter
how that block terminates.  Or else the programmer has to follow rules,
like ``don't branch out of the block''.

In Lisp, this is taken care of. You can branch out of the block using GO,
you can return, signal a condition or throw.  In all cases, the special
variable overridden in that block is restored.  You could cob something
like this together using setf and unwind-protect:

  (defmacro dynamically-bind (special-var new-value &body forms)
    (let ((saved-var-sym (gensym "SAVED-")))
      `(let ((,saved-var-sym ,special-var))
	(unwind-protect
	  (progn (setf ,special-var ,new-value)
		 ,@forms)
	  (setf ,special-var ,saved-var-sym)))))

but the beauty of special variables is that they are integrated into the
language. Thus you can save and restore them with any binding construct that is
normally used for lexical variables, and you can save and restore a toplevel
unbound state, which would make the above macro's expansion blow up when it
tries to save the old value.