Question about intern and symbols
Question about intern and symbols
I want to generate and initialize a symbol dynamically in SBCL. If given I string "TEST", I want to evaluate to:
(setf TEST 5)
so far I am able to run:
(intern "TEST")
TEST
but this doesn't work:
(setf (intern "TEST") 5)
The function (SETF INTERN) is undefined.
I did however just find a 'historically important' function that works just fine:
(set (intern "TEST") 5)
5
CL-USER>TEST
5
So what's the story with setf, am I just trying to misuse lisp?
(setf TEST 5)
so far I am able to run:
(intern "TEST")
TEST
but this doesn't work:
(setf (intern "TEST") 5)
The function (SETF INTERN) is undefined.
I did however just find a 'historically important' function that works just fine:
(set (intern "TEST") 5)
5
CL-USER>TEST
5
So what's the story with setf, am I just trying to misuse lisp?
Re: Question about intern and symbols
SETF is serious magic. It can set many places, for example hash-table entries, array elements, or just arbitrary symbols. It is a macro that will analyze what kind of place its first (or rather, all odd) argument is, and call the appropriate setter function. If it doesn't know the kind of place, it cannot work.
So, you should read about what a place is to understand what SETF does. In manuals, you will often find a remark "setfable" with accessor functions, which indicates that this accessor function can be used as a place for SETF, as in:
For your intentions, SET seems to be the right choice. If you want to access dynamic variables, SYMBOL-VALUE is setfable (but this only works for dynamic variables).
So, you should read about what a place is to understand what SETF does. In manuals, you will often find a remark "setfable" with accessor functions, which indicates that this accessor function can be used as a place for SETF, as in:
Code: Select all
(setf (gethash key hash-table) value)
"Just throw more hardware at it" is the root of all evil.
Svante
Svante
Re: Question about intern and symbols
In fact, the standard says:Harleqin wrote:For your intentions, SET seems to be the right choice. If you want to access dynamic variables, SYMBOL-VALUE is setfable (but this only works for dynamic variables).
Code: Select all
(set symbol value) == (setf (symbol-value symbol) value)
Anyway, I believe this is one of those cases where asking "why do you want to do that" is warranted. In almost all cases for associating strings or symbols with values dynamically hash tables are better.
Re: Question about intern and symbols
I was interested in making a list of symbols that would be easy to manipulate as a list and yet could have all of the cool features of symbols. I had been looking at Paul Grahams Double-Linked List Structure and thought it was cool, but didn't like that it seemed like I would have to reinvent alot of functionality that was already in normal lists. I don't want to do 'wierd things' though and had strongly considered looking at hashes. I am interested in making a general html menu structure or class that can handle many sub-menus when appropriate yet also know given a page name where it fits in the structure. I have read that plists are both very cool (Graham) and are somewhat archaic (Steele). In this snippet below, if you know that a current page is 'MAIN, then without searching, you also know that it is a member of TOPMENU. I had envisioned only using these symbols in a special HTML package, so as to be isolated and can't really imagine over 50 of these symbols loaded up at any given time.Ramarren wrote: Anyway, I believe this is one of those cases where asking "why do you want to do that" is warranted. In almost all cases for associating strings or symbols with values dynamically hash tables are better.
(setf TOPMENU (list 'MAIN 'GALLERY 'ABOUT 'CONTACT))
(setf MAIN(list 'MAIN_SUB1 'MAIN_SUB2))
(setf (get 'MAIN 'URL) "main.html")
(setf (get 'MAIN 'TITLE) "Main Page of Website")
(setf (get 'MAIN 'PARENT) 'TOPMENU)
Maybe this will just lead to inflexibility and more wierdness down the road and I should go back to looking at a combination of structures or classes and hash tables.
Thanks, hope this makes (some) sense, if you think this is odd, you should see what I was doing to php

Re: Question about intern and symbols
Paul Graham has a very specific style, since he doesn't like large part of Common Lisp, like LOOP or CLOS, so following his advice will often lead to Scheme-like code. There is nothing fundamentally wrong with that, but this is relatively uncommon among programs written in Common Lisp, and might be considered archaic or unidiomatic. Fortunately, there is no such thing as unified Lisp community, so it doesn't matter that much.
Symbol plists also are, obviously, global values, and all problems with global variables apply. For the problem you describe I would just use CLOS classes and hashtables, especially if the structure is well defined.
Symbol plists also are, obviously, global values, and all problems with global variables apply. For the problem you describe I would just use CLOS classes and hashtables, especially if the structure is well defined.
Re: Question about intern and symbols
That's an interesting question. In Common Lisp, "global" variables are special, i.e. dynamic, not really global. It may at first seem the same, but this mediates the problems associated with global variables to some extent. Does this also apply to symbol plists? Can you dynamically handle symbol plists?Ramarren wrote: Symbol plists also are, obviously, global values, and all problems with global variables apply.
"Just throw more hardware at it" is the root of all evil.
Svante
Svante
-
- Posts: 447
- Joined: Sat Jun 28, 2008 7:49 am
- Location: Austin, TX
- Contact:
Re: Question about intern and symbols
No, not automatically. Symbol plists are a separate "attribute" of the symbol, so to speak. They are not affected by the symbol's value. You could, of course, write macros to save/restore the plist values and create the same effect, but you'd have to do it by changing the plist value manually, not simply using LET.Harleqin wrote:That's an interesting question. In Common Lisp, "global" variables are special, i.e. dynamic, not really global. It may at first seem the same, but this mediates the problems associated with global variables to some extent. Does this also apply to symbol plists? Can you dynamically handle symbol plists?Ramarren wrote: Symbol plists also are, obviously, global values, and all problems with global variables apply.
Cheers, Dave
Slowly but surely the world is finding Lisp. http://www.findinglisp.com/blog/
Slowly but surely the world is finding Lisp. http://www.findinglisp.com/blog/
Re: Question about intern and symbols
Thanks, Dave, that cleared up a lot for me.
Of course, this begs some new questions. Is there a tutorial somewhere that explains the inner workings of dynamic and lexical variables with respect to CL's symbols?
Of course, this begs some new questions. Is there a tutorial somewhere that explains the inner workings of dynamic and lexical variables with respect to CL's symbols?
"Just throw more hardware at it" is the root of all evil.
Svante
Svante
-
- Posts: 447
- Joined: Sat Jun 28, 2008 7:49 am
- Location: Austin, TX
- Contact:
Re: Question about intern and symbols
Not that I can think of off-hand. Here's the shortest tutorial that I can think of...Harleqin wrote:Thanks, Dave, that cleared up a lot for me.
Of course, this begs some new questions. Is there a tutorial somewhere that explains the inner workings of dynamic and lexical variables with respect to CL's symbols?

- A symbol is a first-class object. When the reader interns a symbol, a full data structure corresponding to the symbol is created for it. This is in contrast to C where a variable name only exists in the source text and ceases to exist once the compiler has done its thing.
- A symbol has a few things associated with it, including a data value (stored in the value cell), a function value (stored in the function cell), and a plist. The data value is the top-level global value. The function value is the function or macro associated with that symbol (I believe most implementations use a property in the plist to indicate a macro vs. a function).
- You can access the value cell with SYMBOL-VALUE.
- You can access the function cell with SYMBOL-FUNCTION
- You can access the plist with SYMBOL-PLIST
- So, the global (special) value of a symbol is stored right "in" the symbol itself. When you bind a special variable, it reassigns the SYMBOL-VALUE using the strategy of storing away the old value in a temporary, setting the SYMBOL-VALUE to the new value, and then restoring the old value when the binding form (e.g. LET) exits.
- If bind a local variable, it essentially creates a mapping between the symbol and its value (mentally, imagine a hash table or an association list and you have the idea). The lexical binding is simply that, a binding between the symbol and its value. The value is not stored "in" the symbol itself as it is for the SYMBOL-VALUE.
- A compiler can optimize away all the information about lexical variable names during the course of its analysis. Since the storage for a lexical binding is not specified, the compiler is free to do anything it wants (it can store the values anywhere, in a block of memory associated with a closure, on the stack, on the heap, or whatever). The symbol used in the binding simply serves as a name in the source code, so the compiler is free to "forget" what symbol was bound to what in the actual object code emitted (think of this very much like C, where your binary may know that a value is stored at a given location, but has no knowledge of what you named that variable in your source code).
- This is not at all the case with globals. All symbols conceptually have a value cell. There are various ways to implement the storage, but the programmer is always able to access the value cell using SYMBOL-VALUE.
Cheers, Dave
Slowly but surely the world is finding Lisp. http://www.findinglisp.com/blog/
Slowly but surely the world is finding Lisp. http://www.findinglisp.com/blog/
Re: Question about intern and symbols
Very nice!
So:
So:
Code: Select all
CL-USER> (defparameter *test* 1)
*TEST*
CL-USER> *test*
1
CL-USER> (symbol-value '*test*)
1
CL-USER> (let ((*test* 2))
(symbol-value '*test*))
2
CL-USER> (let ((*test* 2))
(setf (symbol-value '*test*) 3)
(print *test*)
(print (symbol-value '*test*)))
3
3 3
CL-USER> (symbol-value '*test*)
1
CL-USER> (setf (symbol-value '*test*) 4)
4
CL-USER> (symbol-value '*test*)
4
CL-USER> *test*
4
"Just throw more hardware at it" is the root of all evil.
Svante
Svante