Not just a normal variable. I’m special!

In my list of Common Lisp notes, I wanted to get on to handler-case and handler-bind,  but I think before I do that I ought to try to explain a little about special variables.
 
Normal variables in Lisp are lexically scoped. When you bind them in a let expression or as arguments to a function, the variable can only be accessed within the lexical scope.
 
(progn
  (let ((x 20))
     … I can reference x anywhere here …
  )
  … But I can’t access it here …
)
 
The extent of the variable however, may be larger than when the scope is active, so in the following example, the location x is shared by the two closures that can access it for  reading and writing.
 
CL-USER 1 > (let ((x 10))
              (cons #'(lambda () x)
                    #'(lambda (y) (setq x y))))
(#<anonymous interpreted function 217DC1C2> . #<anonymous interpreted function 217DB012>)
CL-USER 2 > (funcall (car *))
10
CL-USER 3 > (funcall (cdr **) 20)
20
CL-USER 4 > (funcall (car ***))
20
 
Special variables allow the same location to be accessed outside the lexical scope of any binding.
 
(defun outer ()
  (let ((x 10))
    (declare (special x))
    (inner)))
 
(defun inner ()
  (declare (special x))
  (print x))
 
CL-USER 7 > (outer)
10
10
 
Note that special bindings nest, so that in the following the first call of (inner) accesses the nested binding of x, which is restored for the second call to (inner).
 
(defun outer2 ()
  (let ((x 10))
    (declare (special x))
    (let ((x 20))
      (declare (special x))
      (inner))
    (inner)))
 
CL-USER 10 > (outer2)
20
10
10
 
The same variable can be used as special and non-special in the same form, so that in the following example, (inner) references the special bound x which is bound by the first let but not the second.
 
(defun outer2 ()
  (let ((x 10))
    (declare (special x))
    (let ((x 20))
      (inner))
    (inner)))
 
CL-USER 11 > (outer2)
10
10
10
 
To avoid the need to keep adding the special declarations, a variable can be declared special globally by
 
CL-USER 12 > (proclaim ‘(special y))
NIL
 
or more usuallly by using defvar or defparameter to define a variable which has the side-effect of making it special.
By convention, special variables are usually named with leading and trailing *, ie *x* would have been a more conventional name to use in  the above examples.
 
In a multi-threaded Common Lisp, a binding of a special variable is thread local, making them very much like thread local variables that you find in other languages. There is one big difference though. In other languages, a thread local is implemented as something like:
 
  try 
  {
     … store old value of the thread local variable location …
     … put new value into the location …
     … do something …
  }
  finally
  {
     … restore the old value into the thread location …
  }
 
This kind of code doesn’t behave well in the presence of asyncronous exceptions, like the ThreadAbort exception of C# which could happen when the finally is entered but before the restore happens, leading to the unwinding of the binding not happening.
 
With the Common Lisp equivalent,
 
(let ((*x* 10))
  … do something …
)
 
the Lisp system guarantees that the unwinding happens.
 
How are specials normally implemented? The implementations I have worked on used a technque called shallow binding. The symbol-value slot of the  symbol is used to hold the current value. When a special bindings is made, the old value is pushed on to the stack and chained into a linked list of current bindings. When a non-local return (such as a throw) happens, the  bindings list can be used by the runtime system to unwind special bindings whose stack frames are no longer active. This technique is good in that accessing the current value justs means accessing the value slot of the symbol so it is fast. However, this simple technique only works on uniprocessor implementations and requires that whenever the Lisp thread changes, the bindings for the current thread need to be undone and the bindings for the new thread need to be switched in.
 
The way that special binding interacts with the contours of the stack gives special variables many uses. Hopefully, I’ll get on to them soon.
 
Advertisements
This entry was posted in Computers and Internet. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s