[comp.lang.lisp] Basic Lexical Variable Question

hume@dover.uucp (Chris Hume) (12/21/88)

An incredibly naive question - the answer to which,
I suspect, may be that the question would not arise
given adequate understanding of the role of Lexical
Variables:

In the form below, is there any way to achieve the
binding for "value" without giving it an initial value?

(do ((computed nil)
     (value nil))
    (computed (print value))
    (setq value 1)
    (setq computed t))

I know that Lexical Variables are not considered to
be "bound" in the same sense that Special Variables
are.  It may further be a distinct ADVANTAGE that
they will always "represent" some value, but is the
notion of an UNINITIALIZED Lexical Variable somehow
a contradiction in terms?

Coming at the question from another direction:
the value below is, of course, 1 (and not 2.)

(let ((variable 0))
  (set 'variable 1)
  (setq variable (1+ variable)))

In this case "(set (quote variable) foo)" and
"(setq variable foo)" are NOT equivalent!

Is it even POSSIBLE for Common Lisp to provide
the functionality of "set" to Lexical Variables?

Thanks in advance, for any clarification.
Chris
-- 
Christopher N. Hume		Net: ...!sun!sunburn!dover!hume
MOTOROLA, Inc.		 	M/D: DOV05
2222 South Dobson Road		Tel: (602) 994-6835
Mesa, AZ  85202			FAX: (602) 994-6895

barmar@think.COM (Barry Margolin) (12/21/88)

In article <611@dover.uucp> hume@dover.uucp (Chris Hume) writes:
>An incredibly naive question - the answer to which,
>I suspect, may be that the question would not arise
>given adequate understanding of the role of Lexical
>Variables:

Actually, I think they were relatively good questions, and quite
common among programmers who originally learned Lisp in the days of
dynamic scoping.

>is there any way to achieve the
>binding for "value" without giving it an initial value?

No.  All the Common Lisp mechanisms for binding a lexical variable
give it an initial value.

>but is the
>notion of an UNINITIALIZED Lexical Variable somehow
>a contradiction in terms?

I don't think it's a contradiction, but CL simply doesn't provide any
mechanisms for dealing with such things.  There would need to be
special forms that serve as lexical versions of BOUNDP and MAKUNBOUND,
for instance.  Rather than add this complexity, the concept simply
doesn't exist.

Note that particular implementations may support such a facility.  For
example, in Genera you can do

	(let ((value nil))
	  (variable-makunbound value)
	  ...)

In fact, Genera has a whole bunch of VARIABLE-xxx special forms that
generalize various operations on symbols to operations on all types of
variables (in addition to special and lexical variables, Genera also
has instance variables).

>Is it even POSSIBLE for Common Lisp to provide
>the functionality of "set" to Lexical Variables?

You could do it with your own variant of LET:

(defun better-set (symbol value)
  (set symbol value))

(defmacro better-let (var-specs &body body)
  (let ((vars nil))
    (dolist (spec var-specs)
      (push (if (symbolp spec) spec
	      (car spec))
	    vars))
    `(let ,var-specs
       (flet ((better-set (symbol value)
		(cond
		 ,.(mapcar #'(lambda (var)
			       `((eq symbol ',var)
				 (setq ,var value)))
			   vars)
		 ;; if not bound in the current lexical contour, try the
		 ;; next enclosing one (it's not recursive because I use
		 ;; FLET, not LABELS).
		 (t (better-set symbol value)))))
	  .,body))))

BETTER-LET is just like LET, except that inside it you can use
BETTER-SET in place of SET and it will allow you to set lexical
variables.  The macro is a little complex; here's an example
expansion:

(better-let ((foo 3)
	     (bar nil)
	     baz)
  (better-set 'foo 4)
  foo)

expands into

(LET ((FOO 3)
      (BAR NIL)
      BAZ)
  (FLET ((BETTER-SET (SYMBOL VALUE)
           (COND ((EQ SYMBOL 'BAZ) (SETQ BAZ VALUE))
                 ((EQ SYMBOL 'BAR) (SETQ BAR VALUE))
                 ((EQ SYMBOL 'FOO) (SETQ FOO VALUE))
                 (T (BETTER-SET SYMBOL VALUE)))))
    (BETTER-SET 'FOO 4)
    FOO))

The macro simply creates a runtime symbol table, in effect,
implemented in the COND form.  It could easily be extended to also
support BETTER-SYMBOL-VALUE.  But this portable implementation is
expensive, since it does a linear search of the lexical namespace (SET
can take constant time, since it just stores into the symbol's value
cell).

I hope I haven't confused you more while trying to enlighten you!

Barry Margolin
Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar