"Unspecial" Global Variables?

Discussion of Common Lisp
Post Reply
speech impediment
Posts: 36
Joined: Mon May 04, 2009 5:19 pm

"Unspecial" Global Variables?

Post by speech impediment » Mon Mar 22, 2010 12:19 am

This is from Touretzky's book:

"...it is entirely legal to have a lexically scoped (unspecial) global variable."

This issue has been bothering me: The use of setf for global variables. I have seen this even in Peter Norvig's PAIP. I know you should not use setf like defvar, but it seems that is the case with these books. I have looked at CLtL 2nd edition and it makes no mention of using setf this way, so I am assuming using setf this way is something even older. Here is a typical example from the Touretzky's book that I want to explore further:

Code: Select all

(setf fish '(salmon tuna))

(defun ref-fish () fish)

(defun test-lexical (fish)
	(list fish (ref-fish)))

(test-lexical '(guppy minnow))
((GUPPY MINNOW) (SALMON TUNA))
I have tested this and I got the same result from the book, so it would seem that Touretzky is right. I can use unspecial or "non-dynamic" global variables; although I get warned every time I use setf like that. Touretzky even says I can even ignore the warnings. It appears the result of setf is quite distinct from defconstant and defvar. If I used defvar instead of setf, the result would be ((GUPPY MINNOW) (GUPPY MINNOW)). If I replaced setf with defconstant, I would get an error message. My question is this: What in the world would "unspecial" global variables be useful for? If it is useful, would there be a better way to do this instead of using setf?

ramarren
Posts: 613
Joined: Sun Jun 29, 2008 4:02 am
Location: Warsaw, Poland
Contact:

Re: "Unspecial" Global Variables?

Post by ramarren » Mon Mar 22, 2010 2:03 am

SETFing an undefined variable is not defined by the spec, and so the implementations are free to do whatever they want. Most will either make the variable special, or just set SYMBOL-VALUE, which is how you can obtain the effect without warnings:

Code: Select all

(setf (symbol-value 'fish) '(salmon tuna))

(defun ref-fish () (symbol-value 'fish))

(defun test-lexical (fish)
  (list fish (ref-fish)))

(test-lexical '(guppy minnow))
I don't think this actually counts as a lexical global, though. There are more elaborate lexical variables using DEFINE-SYMBOL-MACRO, like this one.

I don't think those are actually useful for anything in practice. It might be nice to have those when testing code from the repl, as you would be able to define top-level variables without earmuffs without worrying about name conflicts, but that just saves a few characters.

nuntius
Posts: 538
Joined: Sat Aug 09, 2008 10:44 am
Location: Newton, MA

Re: "Unspecial" Global Variables?

Post by nuntius » Mon Mar 22, 2010 9:43 am

I think the following example shows the SPECIAL distinction nicely.

Code: Select all

(setf (symbol-value 'var-normal) 42)
(setf (symbol-value 'var-special) 42)
(declaim (special var-special))

(defun list-vars ()
  (list var-normal var-special))

(defun test-vars ()
  (let ((var-normal 5)
        (var-special 5))
    (list-vars)))

speech impediment
Posts: 36
Joined: Mon May 04, 2009 5:19 pm

Re: "Unspecial" Global Variables?

Post by speech impediment » Thu Mar 25, 2010 12:34 am

It is interesting that SETFing an undefined variable is undefined since even Graham himself said this in his ANSI common lisp book: "Global variables established by calling setf at the toplevel are implicitly
special". I don't understand why there is so many different interpretations of setf even after ANSI standardization. No one likes to leave it undefined. Although my example code doesn't really count as lexical, the result I got back using SBCL (as well as nuntius's example) indicates it doesn't behave like a special variable either... Even though Rammaren said most implementations will make it special, I will most likely avoid this whole business of setf for undefined variables.

Post Reply