On first look it seems somewhat silly to have a function which returns the name of a symbol, which must be called using the name of that same symbol. i.e. it should already be obvious in the calling context what the function will return. On the other hand there is identity which is sometimes useful (I forget where just now) but I supposed (perhaps wrongly) that symbol-function is there for a reason other than simply to act as a kind of identity.
However, the hyperspec offers a possible hint:
(symbol-name 'temp) => "TEMP"
(symbol-name :start) => "START"
(symbol-name (gensym)) => "G1234" ;for example
I note that :start means get the name of the symbol start from the keyword package, where the keyword package is denoted simply by :.
(:keyword being its longer form, unnecessary to use). Thus, in this case symbol-name plays the role of simply removing the package prefix.
The other thing it might do is, given an implementation is case insensitive, it would get the actual name by removing case in the symbol name supplied.
Is that roughly it or is there any importance to this function I am missing?
One thing I was confused by about symbols (cleared up now) is that symbol-plist does not tell you everything about the symbol (say, whether it holds the value of a special variable or function). Rather, plist is a mainly legacy feature now largely replaced by hashtables. So, a call to symbol-plist is going to return NIL even if one has set a special variable on the symbol.
One final question on that, Paul Graham says in Chapter 8 (p133), that "You can use symbols as data objects and as names for things without understanding how the two are related". Would it be correct say that if we rarely now use plists, that, today, we generally don't use symbols "as data objects" at all, instead, just as names for things (allbeit with the duality in CL of course, i.e. symbol-function and symbol-value simultaneously).
Symbols are objects. You can create them and pass them around programmatically. One of the properties of these objects is their name, which is a string. Symbol-name is the reader (not accessor) for that. That's all.
Symbols are also used in the representation of code. In this case, they are created by the reader and used by the compiler. This is not their only use, however, and the spec makes no such assumptions either. I hope that this addresses the core of your question.
Here is a function that, given a symbol, returns a symbol interned in the same package but with a reversed name:
(defun reverse-symbol (symbol)
(intern (make-symbol (reverse (symbol-name symbol)))
(symbol-package symbol)))
Here is a function that, given a string designator, returns the designated string:
(defun designated-string (string-designator)
(ctypecase string-designator
(string string-designator)
(symbol (symbol-name string-designator))))
You can also do all kinds of shenanigans in macros and compiler macros by inspecting the names of the symbols in the given form and applying some conventions (not that you should…).
Let's assume you want to write some protocol for transmitting bits of structure between two different systems over some serial channel
(defgeneric transmit-object (o stream))
What is the method for symbols going to look like?
(defmethod transmit-object ((o symbol) stream)
... (symbol-name o) ...)
In particular you certainly do not know the name of the symbol at the point where you need to reason about it, and you could not write such a protocol without using symbol-name (or some absolutely appalling hack like printing the symbol to a string and using that).
Regarding symbol-plist, the implementation is completely at liberty to keep all sorts of information on the property list of a symbol. I am not even sure that the implementation is not allowed to do (a cleverer version of):
(defun symbol-value (s)
(let* ((d (load-time-value (cons nil nil)))
(v (get s secret-value-indicator d)))
(when (eq v d)
(error ...))
v))
It may be that this is not allowed, but I am not sure. Certainly it was once fairly common for function definitions to be kept in this way.
It's not so silly when you process symbol names. When you for example build preprocessor - you read some data, convert it to list structures and then some code is processing those list and trigger some additional logic when symbol-name is lets say defun-my-ubermacro. It's exactly what's in Graham quote - you treat symbols as data.
And (in my opinion) it's not correct to say, that when you don't use plists, you generally don't use symbols as data. Plists are only on of many places where it's useful feature. A lot of what macros do is processing symbols as data / names.
On first look it seems somewhat silly to have a function which returns the name of a symbol, which must be called using the name of that same symbol.
That's wrong. symbol-name is called with a symbol and not a name. It returns the name as a string.
I note that :start means get the name of the symbol start from the keyword package, where the keyword package is denoted simply by :. (:keyword being its longer form, unnecessary to use). Thus, in this case symbol-name plays the role of simply removing the package prefix.
No, symbol-name returns the name of the symbol as a string. The keyword symbol is an object of type symbol.
A symbol is a data type and has several cells:
the name, a string
possibly a function
possibly a value
a property list
optionally the home package it is interned in
don't use symbols "as data objects" at all, instead, just as names for things
No, symbols as data objects have many purposes. For example Lisp source code uses many symbols. But it can also appear in all sorts of data.
CL-USER 6 > 'foo
FOO
CL-USER 7 > (type-of 'foo)
SYMBOL
CL-USER 8 > (symbol-name 'foo)
"FOO"
CL-USER 9 > (type-of (symbol-name 'foo))
SIMPLE-BASE-STRING
CL-USER 10 > (mapcar #'symbol-name '(a b c defun foo bar))
("A" "B" "C" "DEFUN" "FOO" "BAR")
CL-USER 11 > (mapcar #'type-of *)
(SIMPLE-BASE-STRING SIMPLE-BASE-STRING SIMPLE-BASE-STRING SIMPLE-BASE-STRING SIMPLE-BASE-STRING SIMPLE-BASE-STRING)
Since you haven't accepted an answer, here is my take.
For most day-to-day programming symbols, and therefore SYMBOL-NAME,
aren't very useful. Mostly they are used for their
unique-ness. However they shine when you are modifying the compiler
with macros.
Here are 3 examples where SYMBOL-NAME is used:
Firstly, LOOP is the CL generic looping construct, it works via
placeholder symbols in a way that some claim is un-lispy, but it
remains very handy, especially if you are stepping things in parallel.
The following 3 forms are equivalent (at run-time):
(loop for i in list collect i)
(loop :for i :in list :collect i)
(loop #:for i #:in list #:collect i)
I, personally, prefer the third form because it makes it really
obvious where the LOOP magic is happening, and also avoids interning
symbols in any package (which is usually harmless, but not
always). That the third works at all requires the existence of
SYMBOL-NAME
Secondly, I don't make much use of CLOS but classes are undeniably
useful. DEFCLASS tends to be too verbose for what I want to do though,
so I often employ a macro that uses implied symbols. So:
(defbean peer ()
(id)
(next
beats))
Becomes:
(defclass peer nil
((id :initarg :id :reader peer-id)
(next :initarg :next :accessor peer-next)
(beats :initarg :beats :accessor peer-beats)))
Saving much typing. Notice how the slot name is converted to a keyword
for the initargs, and how reader and accessor names are created.
Some don't like this sort of macro, and I can see how it might be
problematic if you have a large team with everyone doing this all over
the shop (though M-. and C-c ret are always available), but for
small teams I think this is one of the best reasons to use lisp,
customising it to how you actually want to use it.
Thirdly, my sqlite helper library uses SYMBOL-NAME to generate SQL
statements (along with some more implied symbols) for even more
code-saving:
(defsqlite-table artists
(id :auto-key)
(artist-name :t)
(sort-artist-name :t :n))
Becomes something pretty huge:
(progn
(defparameter +create-artists-sql+
"CREATE TABLE artists (
id INTEGER PRIMARY KEY NOT NULL,
artist_name TEXT NOT NULL,
sort_artist_name TEXT
)")
(defun create-artists-table (pjs-sqlite::db pjs-sqlite::recursive log)
###)
(eval-when (:load-toplevel)
###)
(defun insert-artists
(pjs-sqlite::db artist-name sort-artist-name &key (id nil id-p))
###)
(defun update-artists
(pjs-sqlite::db id
&key (artist-name nil artist-name-p)
(sort-artist-name nil sort-artist-name-p))
###)
(defun delete-artists (pjs-sqlite::db id)
(with-sqlite-statements (pjs-sqlite::db
(pjs-sqlite::stmt
"DELETE FROM artists WHERE id = ?"))
###)))
(I stripped out a lot of code that would be distracting, but it should
be clear how I mapped symbols to sql identifiers)
I hope this gives you some ideas on what sort of things SYMBOL-NAME
can be used for.
I have a macro which defines a class under certain rules, pseudo-code :
(defvar *all-my-classes* nil)
(defmacro my-macro (param)
`(if ,param
(progn
(defclass class-A () ...)
(push class-A *all-my-classes*))
(progn
(defclass class-B () ...)
(push class-B *all-my-classes*))))
I want to test the behaviour of the macro. Let is a convenient tool to mock variables. If I have an instance of *all-my-classes* running, I just have to do :
(let ((*all-my-classes* my-new-value)) ; generally `nil` for the test
(my-macro false))
But I would like to conserve the correspondance between *all-my-classes* and the classes defined. Since I want to test all the cases, let us suppose class-A is defined in the current environment, and i want to test if running (my-macro false) correctly defines class-B.
Since it is just a test, I would like the test to assert that class-B is currently defined, and that class-A is undefined in the current local environment; then when the test is over, class-B is undefined in the global environment, and class-A is still defined (without any alteration).
This way would be the best for my use :
(let ((*all-my-classes* nil))
(class-let ((class-A nil) ; or a way to map to a pre-defined
(class-B nil)) ; empty class temporarily.
(my-macro false)
(and
;; assert that the class is added to the list
(eql (length *all-my-classes*) 1)
;; assert that class-A is not defined
(null (find-class 'class-A))
;; assert that class-B is defined
(find-class 'class-B))))
I've searched to see if I can undefine a class, but it seems to be complex and implementation-dependent. And I want to preserve the current environment.
Restarting LISP each time for each tests is too long, and I would prefer a solution without having to load-unload packages for each tests (I don't know if it could work and if the classes will be garbage-collected when unloading the package...).
Thank you for your answers.
I do not think so.
The mechanism of how classes are stored is completely implementation defined, they just need to conform to the MOP (at least as far as it is mandated by the standard). However, the MOP does not prescribe anything that would make the classes registry dynamic. In fact, types and class names are specified to be part of the global environment (CLHS ch. 3.1.1.1), so it would be difficult for a conforming implementation to get dynamic here.
As you wrote, there is also no specified way to get rid of a class once defined.
As a rationale, I think that without this it would be very difficult to provide the kind of optimized runtime that the existing implementations have. Class lookup needs to be fast.
Now, to get to the meta question: what are you trying to do? Usually, while code is data, you should not confuse program logic with the programmed logic. What you propose looks like it might be intended to have code represent data. I'd advise to think about a clean separation and orthogonal representation.
I have a global list of words (symbols) and I want to write a function that can add new words to it. I can add new words but then I run into errors that they are unbound. how can I write a function:
(defun add-symbol (aNewWord) (... ))
and have it create a global symbol
using the argument I type as its name?
Perhaps I would like a user to add new symbols during runtime.
Use PUSH to add an element to a list.
(defvar *word-list* ())
(defun add-symbol (new-word)
(push new-word *word-list*))
(add-symbol 'hello)
(add-symbol 'friday)
*word-list*
Output is:
(FRIDAY HELLO)
If you were getting errors about unbound variables, you probably forgot to quote the symbols when you used them as arguments to the function. If you don't quote a symbol, it's treated as a variable name and tries to use its value.
Generally, you want to control the namespace for user created data and not have it leak into your program structure. It is thus preferable to create some (maybe top level) datastructure inside of which you hold the data. Do not create variables from user data.
Keys for such data might be symbols, which you can create with intern. If you want to create new symbols with names given by the user, you might want to use either the keyword package:
(defun make-user-symbol (string)
(intern string '#:keyword))
or some pristine package for exactly those symbols:
(defpackage #:user-symbols)
(defun make-user-symbol (string)
(intern string '#:user-symbols))
One flexible data structure for such things are hash tables:
(defvar *user-data* (make-hash-table :test #'eq))
(defun add-user-data (keystring value)
(setf (gethash (make-user-symbol keystring) *user-data*)
value))
You could also just use strings, of course, but then the hash table needs to use :test #'equal.
If you want to have a set of words as symbols (though I do not see the need for such a conversion), your data structure might be a list:
(defvar *words* ())
(defun add-word (string)
(push (make-user-symbol string) *words*))
The generic function slot-definition-readers gets an argument that must be a direct-slot-definition. If an object is an instance of a class that inherits from another class how can I get hold of the readers of all the effective-slots of the object? Do I manually have to traverse the tree and call slot-definition-readers on the result of class-direct-slots in each superclass, gathering the results, or is there another way that I am not aware of?
This "community wiki" answer is here to provide an implementation of this feature. What follows uses no destructive operation (NCONC, MAPCAN) since an implementation might return an internal list without copying it. MAPPEND is imported from alexandria, and MOP operations can be imported from closer-mop.
(defun all-direct-slots (class)
(append (class-direct-slots class)
(mappend #'all-direct-slots
(class-direct-superclasses class))))
(defun all-slot-readers (class)
(mappend #'slot-definition-readers
(all-direct-slots class)))
I've been using noir in a web project and I came up to the point of restricting access to users, depending on their access level (and sublevel) to all possible routes defined by a defpage macro. So originally I had
(defpage [:post "/mysite"] {:as input}
(if-not (has-reqd-user-level? :levelX :sublevelY "/grantedRoute")
(noir.response/redirect "/insufficientRights")
...))
And then I thought this would get rid of boilerplate code:
(defmacro defpage-with-user-level [level sublevel granted-route route data expr]
`(defpage ~route ~data
(if-not (has-reqd-user-level? ~level ~sublevel ~granted-route)
(noir.response/redirect "/insufficientRights")
~expr)))
Finally, we use it as follows:
(defpage-with-user-level :levelX :sublevelY "/grantedRoute"
[:post "/mysite"] {:as input}
(html
[:body [:h1 (str "Hello " (:name input) "!")]]))
But as mentioned in this post made by Rich Hickey, https://groups.google.com/forum/#!msg/clojure/4II-HKr_Pu0/2IcKit99cagJ , it feels a little bit awkward because of positional binding, which is not idiomatic when there already exist maps.
However, I've been looking for some examples or discussions regarding the use of destructuring bindings in macros, and sadly, I hadn't found any clear use of them, because of its unevaluated expressions being passed through all along.
So, the following solution came to my mind:
(defmacro defpage-with-user-level [dts expr]
`(defpage (:route ~dts) (:data ~dts)
(if-not (has-reqd-user-level? (:level ~dts) (:sublevel ~dts) (:granted-route ~dts))
(noir.response/redirect "/insufficientRights")
~expr)))
But now, it's not clear how to pass the data map that maps locals from :get and :post into a local as in the examples above.
Am I doing right leaving my first attempt untampered or do I really need to use the second approach? I hope not. Is there any other option? Please, let me know.
Your first solution is fine. What Rich was talking about was using plain old maps to passing data around rather then creating new types/classes for each type of data. Ex: you can represnt a user information using a simple map rather than creating a class to represent user data.
As far as your second attempt is concerned, you can use map de-structuring in macro as:
(defmacro defpage-with-user-level [{:keys [route data level sublevel granted-route]} expr]
`(defpage ~route ~data
(if-not (has-reqd-user-level? ~level ~sublevel ~granted-route)
(noir.response/redirect "/insufficientRights")
~expr)))
(defpage-with-user-level {:level :levelX
:sublevel :sublevelY
:granted-route "/grantedRoute"
:route [:post "/mysite"]
:data {:as input}}
(html
[:body [:h1 (str "Hello " (:name input) "!")]]))