From: ·············@spamgourmet.com
Subject: Defining variable programmatically, using symbol-value, generates error
Date: 
Message-ID: <1158932025.412215.16450@d34g2000cwd.googlegroups.com>
Hi,

I'm writing an application which wants to set a bunch of global
variables to a bunch of things, and I'm getting an annoying warning.  I
wanted to write a function I could call which does what defvar does in
the REPL, and the best I could come up with was this:

(defun my-set-symbol (name value)
  (if (boundp name)
      (eval `(setf ,name ,value))
    (eval `(defvar ,name ,value))))

It works, but it's pretty ugly to resort to eval like that.  Lately
I've tried replacing it with this more elegant version:

(defun my-set-symbol (name value)
  (setf (symbol-value name) value))

And this works too, but it prints a warning in, for example, this
situation:

(my-set-symbol 'hello "hello world")

(defun foo ()
  hello)

(foo)

This actually works, but it produces this output:

; Warning: This variable is undefined:
;   HELLO
;
"hello world"

Which, you know, just seems unfair.  It was defined when I defined the
function, it's defined now, it's always been defined.  I can tell,
because you actually managed to print the correct contents of the
variable there, so even *you* seem to agree that it's defined.  So
what's with the warning?  It's like defvar is flipping some magic
switch that I'm missing with my (setf (symbol-value ...)) stuff.

I discovered that I can make the warning go away if I define foo as:

(defun foo ()
  (declare (special hello))
  hello)

Which is great and all, but is really inconvenient if I'm going to be
using that variable in a lots of places (which I am).

This is in CMUCL under Debian "Sarge".

Anyone want to tell me what I'm missing?

From: Thomas A. Russ
Subject: Re: Defining variable programmatically, using symbol-value, generates error
Date: 
Message-ID: <ymimz8r4vsj.fsf@sevak.isi.edu>
·············@spamgourmet.com writes:

> Hi,
> 
> I'm writing an application which wants to set a bunch of global
> variables to a bunch of things, and I'm getting an annoying warning.  I
> wanted to write a function I could call which does what defvar does in
> the REPL, and the best I could come up with was this:

OK.  At this point it seems like you already know what global variables
you want to be using.  So this is the place where you would normally use
either DEFVAR or DEFPARAMETER.  Those end up declaring the variables and
(optionally in the case of DEFVAR) setting its initial value.

I don't think you really want to be creating new global variables
dynamically, unless you are also creating the code that references them
dynamically.

> (defun my-set-symbol (name value)
>   (if (boundp name)
>       (eval `(setf ,name ,value))
>     (eval `(defvar ,name ,value))))
> 
> It works, but it's pretty ugly to resort to eval like that.  Lately
> I've tried replacing it with this more elegant version:
> 
> (defun my-set-symbol (name value)
>   (setf (symbol-value name) value))

OK.  Even simpler, given that you've already declared the variables with
DEFVAR or DEFPARAMETER is to just use SETF directly on the variable
name.

> And this works too, but it prints a warning in, for example, this
> situation:
> 
> (my-set-symbol 'hello "hello world")

So, for example, here you would only need

  (setf hello "hello world")

I will point out for completeness that special (read: global) variables
are traditionally named with asterisks around them in Lisp.  This is a
widely followed convention (similar to the C/C++ convention of
uppercasing #define'd constants).  It would be good of you to follow it,
since it makes life easier.


> 
> (defun foo ()
>   hello)
> 
> (foo)
> 
> This actually works, but it produces this output:
> 
> ; Warning: This variable is undefined:
> ;   HELLO
> ;
> "hello world"

OK, the full example would be something like this:

(defvar *hello*)
(setf *hello* "hello world")
(defun foo ()
  *hello*)
(foo)  ==> "hello world"

> Which, you know, just seems unfair.  It was defined when I defined the
> function, it's defined now, it's always been defined.  I can tell,
> because you actually managed to print the correct contents of the
> variable there, so even *you* seem to agree that it's defined.  So
> what's with the warning?  It's like defvar is flipping some magic
> switch that I'm missing with my (setf (symbol-value ...)) stuff.

Actually, it's not defined.  It is only referenced.  In any other
programming language this would be an error.  Lisp, given its heritage
and interactive nature tries to be helpful and automatically make some
assumptions.  A typical assumption made by a lisp compiler is that a
reference to a free variable is treated as a reference to a SPECIAL
variable.  Come lisp implementations (notably CMUCL & probably SBCL) go
a bit further and actually proclaim such an unreferenced variable as
special in addition to treating it so.  (This distinction matters
because then the variable becomes globally special, rather than
locally).

So, the summary advice is to use DEFVAR to declare your global variables
before using them.

Also, in regard to the meaning of the term "special" when applied to
variables.  Normal variables introduced, for example, by LET or by
function paramter lists use lexical scoping.  Special variables, in
contrast use dynamic scoping.  The difference lies in where they are
visible.  For example:

(defvar *special-variable* nil)

(defun foo ()
  (let ((*special-variable* 'foo))
    (bar)))

(defun bar ()
  *special-variable*)

(defun foo2 ()
  (let ((ordinary-variable 'foo))
    (bar2)))

(let ((ordinary-variable 'bar))
  (defun bar2 ()
     ordinary-variable))

(defun foo3 ()
  (let ((*special-variable* 'foo))
    (bar3)))

(let ((*special-variable* 'bar))
  (defun bar3 ()
    *special-variable*))


(bar)  => nil
(foo)  => FOO  because of dynamic scoping.
(bar2) => BAR
(foo)  => BAR  because of lexical scoping.
(bar3) => nil  !! because of dynamic scoping
(foo3) => FOO  because of dynamic scoping

If you can figure out why Lisp behaves this way, you will have
understood the difference between lexical and dynamic (special) scoping
rules.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Christophe Rhodes
Subject: Re: Defining variable programmatically, using symbol-value, generates error
Date: 
Message-ID: <sqwt7vbs8r.fsf@cam.ac.uk>
···@sevak.isi.edu (Thomas A. Russ) writes:

> [S]ome lisp implementations (notably CMUCL & probably SBCL) go
> a bit further and actually proclaim such an unreferenced variable as
> special in addition to treating it so.

Probably not SBCL.  (Definitely not SBCL, actually).

Christophe
From: ·············@spamgourmet.com
Subject: Re: Defining variable programmatically, using symbol-value, generates error
Date: 
Message-ID: <1159021651.296732.143430@d34g2000cwd.googlegroups.com>
Thomas A. Russ wrote:

> I don't think you really want to be creating new global variables
> dynamically, unless you are also creating the code that references them
> dynamically.

This is precisely what I'm doing, although whether *anything* I'm doing
is a good idea is, of course, open to question :-)  I'm only
experimenting really, and learning precisely these kinds of details
about Lisp as I go.

> I will point out for completeness that special (read: global) variables
> are traditionally named with asterisks around them in Lisp.  This is a
> widely followed convention (similar to the C/C++ convention of
> uppercasing #define'd constants).  It would be good of you to follow it,
> since it makes life easier.

On my queue of "things to figure out" was "why do these crazy Lisp
people put asterisks all over the place", so thanks for this.

> Also, in regard to the meaning of the term "special" when applied to
> variables.  Normal variables introduced, for example, by LET or by
> function paramter lists use lexical scoping.  Special variables, in
> contrast use dynamic scoping.  The difference lies in where they are
> visible.
...
> If you can figure out why Lisp behaves this way, you will have
> understood the difference between lexical and dynamic (special) scoping
> rules.

I'm used to the idea of lexical and *global* scoping, and using
proclaim to specify which one you mean, rather than always assuming
lexical scoping where available, makes sense.  It's just that the name,
"special", isn't particularly descriptive.
From: Wade Humeniuk
Subject: Re: Defining variable programmatically, using symbol-value, generates error
Date: 
Message-ID: <A_RQg.32248$cz3.29224@edtnps82>
You can see what CMUCL is doing "under the hood" when you do
a defvar, and then copy its behaviour into your function.

Though I do not have it installed anywhere, with LW I get ...

CL-USER 5 > (pprint (macroexpand '(defvar wade 10)))

(COMPILER-LET ((DSPEC::*LOCATION* '(:INSIDE (DEFVAR WADE) :LISTENER)))
   (COMPILER::TOP-LEVEL-FORM-NAME (DEFVAR WADE)
     (EVAL-WHEN (:COMPILE-TOPLEVEL)
       (COMPILER::ADD-SPECIAL 'WADE 'DSPEC::GLOBAL NIL))
     (DSPEC:INSTALL-DEFVAR 'WADE (DSPEC:LOCATION) (UNLESS (BOUNDP 'WADE) 10))))

CL-USER 6 >

Wade
From: Christophe Rhodes
Subject: Re: Defining variable programmatically, using symbol-value, generates error
Date: 
Message-ID: <sqzmcsovno.fsf@cam.ac.uk>
·············@spamgourmet.com writes:

> Anyone want to tell me what I'm missing?

Defining a variable and setting the value cell of a symbol are
different things.  If you want to define a variable, then define a
variable and reference it; if you want to set the value cell of a
symbol, then reference the value cell of a symbol, not an undefined
variable of the same name.

If you do

  (setf (symbol-value 'foo) 1)

then you can retrieve that value without any warnings with

  (symbol-value 'foo);

On the other hand, if you want to have a (special) variable, you need
to define it; the normal way is to simply evaluate defvar with
statically-known symbols; if you really want to define new special
variables at runtime (which seems unlikely, since you won't have any
code which refers to them) then you can use 

  (proclaim (list 'special symbol))

to inform the compiler that any subsequent code with a variable with a
name which is the value of symbol should treat that variable as a
special.

Christophe
From: ·············@spamgourmet.com
Subject: Re: Defining variable programmatically, using symbol-value, generates error
Date: 
Message-ID: <1158936359.827650.236150@h48g2000cwc.googlegroups.com>
Christophe Rhodes wrote:

> On the other hand, if you want to have a (special) variable, you need
> to define it; the normal way is to simply evaluate defvar with
> statically-known symbols; if you really want to define new special
> variables at runtime (which seems unlikely, since you won't have any
> code which refers to them) then you can use
>
>   (proclaim (list 'special symbol))

Thanks, it was the proclaim bit I was missing.  And also my brain is
clearly too ruined by long-term exposure to C & variants to cope with
the difference between a symbol and a variable which, if it happens to
have the same name as a "special" symbol, takes on the value of said
symbol.  Is there a link you can point me to which explains thoroughly
what's so special about "special"?  I was looking for one earlier, and
couldn't find anything.

It seems I'm not going to make life dramatically simpler by changing my
existing function from "eval defvar" to "proclaim".  I should be
restructuring my code to use symbol-value to both get and set the
values, but that'll also mean removing all the evals I've got for
reading the things, so it's not going to happen this afternoon :-(
From: Pascal Bourguignon
Subject: Re: Defining variable programmatically, using symbol-value, generates error
Date: 
Message-ID: <873bak3pwt.fsf@thalassa.informatimago.com>
·············@spamgourmet.com writes:

> Subject: Defining variable programmatically

variable programmatically ==> PROGV

Have you considered it?  
It seems to me it's the designated tool to do what you want.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

HANDLE WITH EXTREME CARE: This product contains minute electrically
charged particles moving at velocities in excess of five hundred
million miles per hour.
From: ·············@spamgourmet.com
Subject: Re: Defining variable programmatically, using symbol-value, generates error
Date: 
Message-ID: <1158938285.845962.133250@m73g2000cwd.googlegroups.com>
Pascal Bourguignon wrote:

> variable programmatically ==> PROGV
>
> Have you considered it?
> It seems to me it's the designated tool to do what you want.

Well, not really.  I want the results to be globally visible.  If I'm
reading the documentation right, when the progv is finished, the
contents of my variables go away too.  Right?
From: Pascal Bourguignon
Subject: Re: Defining variable programmatically, using symbol-value, generates error
Date: 
Message-ID: <87eju33omv.fsf@thalassa.informatimago.com>
·············@spamgourmet.com writes:

> Pascal Bourguignon wrote:
>
>> variable programmatically ==> PROGV
>>
>> Have you considered it?
>> It seems to me it's the designated tool to do what you want.
>
> Well, not really.  I want the results to be globally visible.  If I'm
> reading the documentation right, when the progv is finished, the
> contents of my variables go away too.  Right?

Indeed.  But perhaps you don't need to exit from PROGV...


If you really need to modify the global environment, why not using
DEFPARAMETER?

(defun store-value (name value)
  (eval `(defparameter ,name ',value)))

(defun store-form (name form)
  ;; WARNING: FORM can only refer global variables.
  (eval `(defparameter ,name ,form)))



-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Kitty like plastic.
Confuses for litter box.
Don't leave tarp around.
From: ·············@spamgourmet.com
Subject: Re: Defining variable programmatically, using symbol-value, generates error
Date: 
Message-ID: <1159020230.973718.221020@i42g2000cwa.googlegroups.com>
Pascal Bourguignon wrote:

> Indeed.  But perhaps you don't need to exit from PROGV...

In this case I'm defining both global variables and the functions that
are going to use the global variables.  And the set of those is
constantly changing.  It's quite likely that I'm not doing this the
best way, but it's more of a learning exercise than anything, so I'm
learning as I go.

> If you really need to modify the global environment, why not using
> DEFPARAMETER?

The bit I found ugly was my use of "eval" more than anything.  So
defparameter vs. defvar doesn't make much difference.  The real
solution is (probably) the one suggested by Christophe Rhodes, that I
can use symbol-value both to set and retrieve the values, rather than
just to set them.  And it would probably make sense to use proclaim as
well, just to make sure me and the compiler are both on the same page.
From: Alan Crowe
Subject: Re: Defining variable programmatically, using symbol-value, generates error
Date: 
Message-ID: <86r6y3q1sc.fsf@cawtech.freeserve.co.uk>
·············@spamgourmet.com writes:

> Hi,
> 
> I'm writing an application which wants to set a bunch of global
> variables to a bunch of things, and I'm getting an annoying warning.  I
> wanted to write a function I could call which does what defvar does in
> the REPL, and the best I could come up with was this:
...
> what's with the warning?  It's like defvar is flipping some magic
> switch that I'm missing with my (setf (symbol-value ...)) stuff.
> 
> I discovered that I can make the warning go away if I define foo as:
> 
> (defun foo ()
>   (declare (special hello))
>   hello)
> 
> Which is great and all, but is really inconvenient if I'm going to be
> using that variable in a lots of places (which I am).
> 
> This is in CMUCL under Debian "Sarge".
> 
> Anyone want to tell me what I'm missing?

DEFVAR is flipping a magic switch. You can flip it yourself
with the function proclaim.

(defun autoset (name value)
  (unless (boundp name)
    (proclaim `(special ,name)))
  (set name value))

There is a little bit of history here. Common Lisp has a
rule that functions don't get run at compile time. However
the file compiler needs to recognise special proclamations,
so initially the function proclaim was going to be an
exception.

X3J13 decided that exceptions to the rules suck. So they
decided not to make an exception for proclaim. If they had
stopped there you would have had to write

(eval-when (:compile-toplevel)
  (proclaim '(special x)))

to get the file compiler to recognise your
declaration. Naturally they added a macro, declaim, to the
language to fix this. With CMUCL you can see declaim being
expanded into a proclaim wrapped in an eval-when.

CL-USER> (macroexpand-1 '(declaim (special x)))
(PROGN
 (EVAL-WHEN (:LOAD-TOPLEVEL :EXECUTE) (PROCLAIM '(SPECIAL X)))
 (EVAL-WHEN (:COMPILE-TOPLEVEL) (C::%DECLAIM '(SPECIAL X))))

and you can see what defvar does

CL-USER> (macroexpand '(defvar x))
(PROGN
 (DECLAIM (SPECIAL X))
 (LISP::SET-DEFVAR-SOURCE-LOCATION 'X (C::SOURCE-LOCATION))
 'X)

That is the magic switch. 

Now for the awkward question: do you really want to flip it?

The human mind loves binary oppositions, left versus right,
dynamic versus static, gay versus straight, special versus
lexical. However CL has three distinct disciplines for the
scope and extent of its variables.

                       variable
                          /\
                         /  \
                        /    \
                       /      \
                      /        \
                     /          \
                    /            \
                   /              \
                  /                \
                 /                  \
                /                    \
       binding by binding      symbol by symbol
               /\
              /  \
             /    \
            /      \
           /        \
          /          \
         /            \
     special        lexical


(proclaim '(special x))

says that every binding of the symbol x uses the same discipline for
scope and extent, and that it is dynamic extent and indefinite scope.
x becomes a dynamic variable (also known as a special variable)

defvar and defparameter also say this, and are the usual way to code it.

Binding by binding discipline defaults to creating lexical
variables, they have lexical scope and indefinite extent.
You get indefinite scope and dynamic extent by writing a
special declaration for every binding that you want it to
apply to.

Here is the classic demonstration

;;;; A closure returns the closed over variable
CL-USER> (let ((x 'outer))
           (declare (special x))
           (let ((x 'middle))
             (funcall (let ((x 'inner))
                        (lambda() x)))))
; Note: Variable X defined but never used.
; 

INNER


;;;; Dynamic variables get the value from where the function
;;;; is called
CL-USER> (let ((x 'outer))
           (declare (special x))
           (let ((x 'middle))
             (funcall (let ((x 'inner))
                        (declare (special x))
                        (lambda() x)))))
; Note: Variable X defined but never used.
; 

OUTER

;;;; The irreversible defvar
CL-USER> (defvar x)
X

;;;; Now they are all dynamic
CL-USER> (let ((x 'outer))
           (declare (special x))
           (let ((x 'middle))
             (funcall (let ((x 'inner))
                        (declare (special x))
                        (lambda() x)))))
MIDDLE

Now you can see the reason for the convention of always
writing (defvar *x*). Having
(let ((x 'middle)) be a special binding with no local
annotation in the source to warn you is asking for trouble.

Back to the question about the magic switch: do you really
want to flip it?

Why can't you just defvar all the global variables that you
need?  If you have code that is defvar'ing arbitary symbols,
then the semantics of code that uses those symbols is going
to depend on whether it was compiled before or after. Not a
happy situation. Perhaps you could reserve a package for
those symbols?

Alternatively you could use the property list of the symbol.
E.G.

(get 'x 'global) and (setf (get 'x 'global) /some-value/ )

GET has an optional default value which comes in handy if
your property might not have an initial value

(incf (get 'my-count 'gobal 0)) works as does
(push 'thing (get 'my-list 'global '()))

I need to warn you about CMUCL. If you setf an uninitialised variable
(try (describe '*top-level-auto-declare*) )
at the top level you get told this:

CL-USER> (setf var 'value)
Warning:  Declaring VAR special.
VALUE

but it has been PROCLAIM'ed special ie symbol by symbol behaviour.



Alan Crowe
Edinburgh
Scotland
From: ·············@spamgourmet.com
Subject: Re: Defining variable programmatically, using symbol-value, generates error
Date: 
Message-ID: <1159020744.338112.139900@h48g2000cwc.googlegroups.com>
Alan Crowe wrote:

...rich post - thanks!

> Why can't you just defvar all the global variables that you
> need?  If you have code that is defvar'ing arbitary symbols,
> then the semantics of code that uses those symbols is going
> to depend on whether it was compiled before or after. Not a
> happy situation. Perhaps you could reserve a package for
> those symbols?

You are absolutely correct about problems arising from the order in
which the code is compiled, and I think I've already run into exactly
that kind of problem, but just tweaked things until "it stopped
happening".  Using a different package sounds like a good way to go,
and I've already tried to do that more than once, but had to stop when
I began smashing the furniture in frustration at how difficult it is to
use packages.  I will probably try again, sometime when I've got the
necessary furniture budget.

I'm effectively using Lisp's symbol table as just a handy lookup table,
so I could also replace that with my own data structure.  This would
make my generated code rather uglier, but would probably save me some
stress in the long run.