What exactly is a symbol in lisp/scheme?


Solution 1

In Scheme and Racket, a symbol is like an immutable string that happens to be interned so that symbols can be compared with eq? (fast, essentially pointer comparison). Symbols and strings are separate data types.

One use for symbols is lightweight enumerations. For example, one might say a direction is either 'north, 'south, 'east, or 'west. You could of course use strings for the same purpose, but it would be slightly less efficient. Using numbers would be a bad idea; represent information in as obvious and transparent a manner as possible.

For another example, SXML is a representation of XML using lists, symbols, and strings. In particular, strings represent character data and symbols represent element names. Thus the XML <em>hello world</em> would be represented by the value (list 'em "hello world"), which can be more compactly written '(em "hello world").

Another use for symbols is as keys. For example, you could implement a method table as a dictionary mapping symbols to implementation functions. To call a method, you look up the symbol that corresponds to the method name. Lisp/Scheme/Racket makes that really easy, because the language already has a built-in correspondence between identifiers (part of the language's syntax) and symbols (values in the language). That correspondence makes it easy to support macros, which implement user-defined syntactic extensions to the language. For example, one could implement a class system as a macro library, using the implicit correspondence between "method names" (a syntactic notion defined by the class system) and symbols:

(send obj meth arg1 arg2)
(apply (lookup-method obj 'meth) obj (list arg1 arg2))

(In other Lisps, what I've said is mostly truish, but there are additional things to know about, like packages and function vs variable slots, IIRC.)

Solution 2

A symbol is an object with a simple string representation that (by default) is guaranteed to be interned; i.e., any two symbols that are written the same are the same object in memory (reference equality).

Why do Lisps have symbols? Well, it's largely an artifact of the fact that Lisps embed their own syntax as a data type of the language. Compilers and interpreters use symbols to represent identifiers in a program; since Lisp allows you to represent a program's syntax as data, it provides symbols because they're part of the representation.

What are they useful apart from that? Well, a few things:

  • Lisp is commonly used to implement embedded domain-specific languages. Many of the techniques used for that come from the compiler world, so symbols are an useful tool here.
  • Macros in Common Lisp usually involve dealing with symbols in more detail than this answer provides. (Though in particular, generation of unique identifiers for macro expansions requires being able to generate a symbol that's guaranteed never to be equal to any other.)
  • Fixed enumeration types are better implemented as symbols than strings, because symbols can be compared by reference equality.
  • There are many data structures you can construct where you can get a performance benefit from using symbols and reference equality.

Solution 3

Symbols in lisp are human-readable identifiers. They are all singletons. So if you declare 'foo somewhere in your code and then use 'foo again, it will point to the same place in memory.

Sample use: different symbols can represent different pieces on a chessboard.

Solution 4

From Structure and Interpretation of Computer Programs Second Edition by Harold Abelson and Gerald Jay Sussman 1996:

In order to manipulate symbols we need a new element in our language: the ability to quote a data object. Suppose we want to construct the list (a b). We can’t accomplish this with (list a b), because this expression constructs a list of the values of a and b rather than the symbols themselves. This issue is well known in the context of natural languages, where words and sentences may be regarded either as semantic entities or as character strings (syntactic entities). The common practice in natural languages is to use quotation marks to indicate that a word or a sentence is to be treated literally as a string of characters. For instance, the first letter of “John” is clearly “J.” If we tell somebody “say your name aloud,” we expect to hear that person’s name. However, if we tell somebody “say ‘your name’ aloud,” we expect to hear the words “your name.” Note that we are forced to nest quotation marks to describe what somebody else might say. We can follow this same practice to identify lists and symbols that are to be treated as data objects rather than as expressions to be evaluated. However, our format for quoting differs from that of natural languages in that we place a quotation mark (traditionally, the single quote symbol ’) only at the beginning of the object to be quoted. We can get away with this in Scheme syntax because we rely on blanks and parentheses to delimit objects. Thus, the meaning of the single quote character is to quote the next object. Now we can distinguish between symbols and their values:

(define a 1)

(define b 2)

(list a b)
(1 2)

(list ’a ’b)
(a b)

(list ’a b)
(a 2)

Lists containing symbols can look just like the expressions of our language:

(* (+ 23 45) (+ x 9)) 
(define (fact n) (if (= n 1) 1 (* n (fact (- n 1)))))

Example: Symbolic Differentiation

Solution 5

A symbol is just a special name for a value. The value could be anything, but the symbol is used to refer to the same value every time, and this sort of thing is used for fast comparisons. As you say you are imperative-thinking, they are like numerical constants in C, and this is how they are usually implemented (internally stored numbers).

Author by


Updated on July 09, 2022


  • dotnetN00b
    dotnetN00b over 1 year

    For the love of the almighty I have yet to understand the purpose of the symbol 'iamasymbol. I understand numbers, booleans, strings... variables. But symbols are just too much for my little imperative-thinking mind to take. What exactly do I use them for? How are they supposed to be used in a program? My grasp of this concept is just fail.

    • dyoo
      dyoo almost 12 years
      One of these things is not like the others. :) You mention "numbers", "booleans", "strings", which are all types of data. Symbols are also part of that category. Variables are not.
    • ccoakley
      ccoakley almost 12 years
      It is worth noting that Ruby also has symbols. :parent is a symbol. You can sort of think of it as an enum or interned string. It maintains its name (useful for understanding), but is not a String type (unless you convert it).
    • Jiacai Liu
      Jiacai Liu about 7 years
    • Christoffer Bubach
      Christoffer Bubach about 2 years
      They are placeholders for numerical offsets while building/compiling. The resulting code will use the RAM address relative to where the binary got loaded. It's basically the whole reason why they made compilers in the first place, user->active = false is a hell of a lot more convenient than 0x7e62af80+0x3e ;)
  • dyoo
    dyoo almost 12 years
    In particular, two symbols can be checked for equality in constant time by using (eq? sym1 sym2). Symbols are not a "Scheme" or "Lisp" concept: they're general. Think of the term "symbol table".(en.wikipedia.org/wiki/Symbol_table) Symbols in a language like Scheme or Racket are just exposing this concept of a value that's like a string, but with this extra property of fast equality checking.
  • John Clements
    John Clements almost 12 years
    Note: as of a few months ago, many other Racket values are interned, as e.g. strings and inexacts and regexps that appear as literals.
  • Greg Hendershott
    Greg Hendershott almost 12 years
    If you're coming from C or C# (just guessing from your username, .NET noob): Use a symbol when you would use an enum in those languages (and the enumerations aren't labels for specific numbers). enum { north, south, east, west } could be 'north 'south 'east 'west. You don't need to "declare" those like you have to in C with enum. Just go ahead and use them. However a symbol can't do enum { north = 123 }. For that you'd need to do it more like a C #define: (define north 123).
  • Sean Allred
    Sean Allred over 6 years
    What about (eq (make-symbol "test") (make-symbol "test"))? I think your statement about symbols being guaranteed to be interned applies only if those symbols are read. Really interesting point about compilers, though; I never thought about it like that :-)