What makes symbols useful is that they are automatically kept unique. There are no two symbols that are distinct objects but have the same name. But of course, there is no rule without exception. In addition to the normal symbols that have been discussed up to now, you can also create special uninterned symbols that behave slightly differently.
To understand what is different about them and why they might be useful, we look at how normal symbols are actually kept unique.
Whenever Guile wants to find the symbol with a specific name, for
example during read
or when executing string->symbol
, it
first looks into a table of all existing symbols to find out whether a
symbol with the given name already exists. When this is the case, Guile
just returns that symbol. When not, a new symbol with the name is
created and entered into the table so that it can be found later.
Sometimes you might want to create a symbol that is guaranteed ‘fresh’, i.e. a symbol that did not exist previously. You might also want to somehow guarantee that no one else will ever unintentionally stumble across your symbol in the future. These properties of a symbol are often needed when generating code during macro expansion. When introducing new temporary variables, you want to guarantee that they don’t conflict with variables in other people’s code.
The simplest way to arrange for this is to create a new symbol but not enter it into the global table of all symbols. That way, no one will ever get access to your symbol by chance. Symbols that are not in the table are called uninterned. Of course, symbols that are in the table are called interned.
You create new uninterned symbols with the function make-symbol
.
You can test whether a symbol is interned or not with
symbol-interned?
.
Uninterned symbols break the rule that the name of a symbol uniquely
identifies the symbol object. Because of this, they can not be written
out and read back in like interned symbols. Currently, Guile has no
support for reading uninterned symbols. Note that the function
gensym
does not return uninterned symbols for this reason.
Return a new uninterned symbol with the name name. The returned
symbol is guaranteed to be unique and future calls to
string->symbol
will not return it.
Return #t
if symbol is interned, otherwise return
#f
.
For example:
(define foo-1 (string->symbol "foo")) (define foo-2 (string->symbol "foo")) (define foo-3 (make-symbol "foo")) (define foo-4 (make-symbol "foo")) (eq? foo-1 foo-2) ⇒ #t ; Two interned symbols with the same name are the same object, (eq? foo-1 foo-3) ⇒ #f ; but a call to make-symbol with the same name returns a ; distinct object. (eq? foo-3 foo-4) ⇒ #f ; A call to make-symbol always returns a new object, even for ; the same name. foo-3 ⇒ #<uninterned-symbol foo 8085290> ; Uninterned symbols print differently from interned symbols, (symbol? foo-3) ⇒ #t ; but they are still symbols, (symbol-interned? foo-3) ⇒ #f ; just not interned.