(setf a-new-symbol 'value) at the top level

Discussion of Common Lisp
Post Reply
garethw
Posts: 43
Joined: Fri Jul 13, 2012 12:56 pm
Location: Ottawa, ON

(setf a-new-symbol 'value) at the top level

Post by garethw » Sun Aug 05, 2012 2:10 pm

I did this inadvertently, but I was surprised by the results, and I was wondering if someone could help explain what I'm seeing

Code: Select all

* (setf westvleteren 12)
;     (SETF WESTVLETEREN 12)
; ==>
;   (SETQ WESTVLETEREN 12)
; 
; caught WARNING:
;   undefined variable: WESTVLETEREN
; 
; compilation unit finished
;   Undefined variable:
;     WESTVLETEREN
;   caught 1 WARNING condition
=> 12
I was not surprised by the warnings, but I was surprised by the fact that it returned a value. So I had a look at what the symbol now contained:

Code: Select all

* westvleteren
=> 12
It got my value. Weird. But what does describe say?

Code: Select all

* (describe 'westvleteren)
COMMON-LISP-USER::WESTVLETEREN
  [symbol]

WESTVLETEREN names an undefined variable:
  Value: 12
; No value

What does "undefined variable" mean, if it has a value? Is this behaviour defined, or is it implementation-dependant?


$ sbcl --version
SBCL 1.0.40.0.debian
~garethw

pjstirling
Posts: 166
Joined: Sun Nov 28, 2010 4:21 pm

Re: (setf a-new-symbol 'value) at the top level

Post by pjstirling » Mon Aug 06, 2012 6:05 am

Some lisps allow this behaviour without error or warning (and users of said lisps tend to be snooty about the fact that sbcl doesn't, e.g. Doug Hoyte in LOL).

Always use defvar for portability

Konfusius
Posts: 62
Joined: Fri Jun 10, 2011 6:38 am

Re: (setf a-new-symbol 'value) at the top level

Post by Konfusius » Mon Aug 06, 2012 6:43 am

Setting a variable at the top level sets the global value of the variable without proclaiming it special. This is useful because if you use a variable x at top level and then enter a defun that also uses a variable named x then x might be mistakenly interpreted as a global variable inside the function. That way you may use any variable name inside the repl without the fear of breaking your program.
garethw wrote:What does "undefined variable" mean, if it has a value?
In Lisp you don't need to declare or define variables. But if you bind a variable like in (let ((x 1)) ...) then the interpreter/compiler has to determine whether x is proclaimed special so it can decide whether x is to be bound lexicaly or dynamicaly. It does this by looking up the symbol in a database that contains all the proclamations (actually, this database is called the binding.) What SBCL wants to tell you is that the binding doesn't contain any proclamations for that variable.
garethw wrote:Is this behaviour defined, or is it implementation-dependant?
It's defined by the ANSI standard.

Kompottkin
Posts: 94
Joined: Mon Jul 21, 2008 7:26 am
Location: München, Germany
Contact:

Re: (setf a-new-symbol 'value) at the top level

Post by Kompottkin » Tue Aug 07, 2012 2:45 am

Konfusius wrote:Setting a variable at the top level sets the global value of the variable without proclaiming it special.
Yes, it does on some implementations, but conforming programs may not rely on this behavior.

In Lisp you don't need to declare or define variables. But if you bind a variable like in (let ((x 1)) ...) then the interpreter/compiler has to determine whether x is proclaimed special [...]
Actually, lexical binding is the default for LET, unless the variable is declared SPECIAL. Top-level variables are a different beast, though---ANSI CL does not specify a way of creating lexical globals. DEFVAR and DEFPARAMETER both globally declare the variables they define SPECIAL.

On the other hand, there are portable ways of defining something that behaves as a global lexical. They generally rely on DEFINE-SYMBOL-MACRO. (Google DEFLEX or DEFLEXICAL; also see the LEXICAL-CONTEXTS package in the MISC-EXTENSIONS library available via Quicklisp.)

garethw wrote:Is this behaviour defined, or is it implementation-dependant?
It's defined by the ANSI standard.
No; setting undeclared variables has undefined consequences. Of course, there is nothing wrong with relying on implementation-specifics when interacting with the REPL. Just be aware that SETQing an undeclared variable may do all sorts of things in general, like implicitly doing a DEFVAR (declaring the variable SPECIAL and thereby potentially causing hard-to-trace problems), or signalling an error.

garethw
Posts: 43
Joined: Fri Jul 13, 2012 12:56 pm
Location: Ottawa, ON

Re: (setf a-new-symbol 'value) at the top level

Post by garethw » Tue Aug 07, 2012 11:33 am

A big thanks for all your insights.
~garethw

Post Reply