Symbolic values in Scheme
- In this reading, we consider one of Scheme’s central kinds of values, symbols.
You’ve just encountered a variety of types in Scheme, including not only many numeric types (integers, reals, rationals, etc.), but also strings, which are used to represent texts of various sorts. In our tour of the basic types used in Scheme, we should consider one more: symbols.
Scheme’s ancestor, Lisp, was originally developed to aid in experiments in artificial intelligence. At the time, a leading theory suggested that intelligence emphasizes symbolic manipulation. Hence, it is sensible that Lisp and Scheme include symbols as a basic type. Evidence also shows that many programs most appropriately work on abstract symbolic value.
So, what is a symbol? A symbol is simply a word (usually) that we use to denote only itself. Unlike a variable, it has no associated value. Symbols are also atomic, we cannot split them apart (as we might a string. The primary operation we perform on symbols is comparison (determining whether two symbols are the same). We can’t even compare two symbols for order. (Should jelly come before or after jam? Who decides?)
When we want to refer to something as a value involved in a computation, rather than as the name of some other value, we put an apostrophe (usually pronounced “quote”) in front of it. In effect, by quoting the symbol, we’re telling Scheme to take it literally and without further interpretation or evaluation:
> 'sample 'sample
We can also create symbols using the
> (quote sample) 'sample
Operations on symbols
So, what can you do with symbols? Not a whole lot. You can determine if
a value is a symbol using the
symbol? procedure and you can determine
if two symbols are the same using the
equal? procedure. Note that
#t for “yes” on
#f for “no”. We’ll return to
those value when we begin to consider conditionals.
> (symbol? 'sample) #t > (symbol? 23) #f > (equal? 'sample 'elpmas) #f > (equal? 'sample 'sample) #t
Oh, you can also create new symbols using the
That procedure is guaranteed to create a new symbol each time you
> (gensym) 'g3457 > (gensym) 'g3501
Symbols vs. names
'sample (with the quote) is very different from
(without the quote). In the first case, Scheme interprets it as a symbol
(an atomic value). In the second, Scheme interprets it as a name for
another value (e.g., something defined with
define). At first, you
may find the distinction a bit confusing. However, as you get used to
programming in Scheme, the distinction will become natural.
> (define sample 85) > 'sample 'sample > sample 85 > (symbol? 'sample) #t > (symbol? sample) #f > (equal? sample 'sample) #f
The problem becomes even worse when you use a name as a symbol, and the name has not been defined.
> (symbol? 'elpmas) #t > (symbol? elpmas) reference to undefined identifier: elpmas
Symbols vs. strings
Symbols seem a lot like strings, don’t they? Why does Scheme provide
both symbols and strings? In part, because the designers really do want
you to think of them differently. The symbol
'jam should refer to a
concotion of sugar, pectin, and fruit, and not to the concatenation of
the letters “j”, “a”, and “m”. The latter is
> (equal? 'jam "jam") #f > (string-ref "jam" 1) #\a > (string-ref 'jam 1) . . string-ref: contract violation expected: string? given: 'jam argument position: 1st other arguments...:
Is the difference really important? Well, it turns out that differentiating strings from symbols can make a difference in some ways. In particular, because we are not able to decompose symbols, most Scheme implementations have some clever behind-the-scenes trickery that makes it much faster to compare two symbols than two strings.
If you have a symbol and really want something you can decompose into
letters, you can use the
symbol->string operation. Similarly, if you
have a string and want a symbol, you can use the
> (symbol->string 'jam) "jam" > (string->symbol "hello") 'hello
Side note: Quoting other values
quote does not create a symbol. Rather, it tells Scheme to take something literally. Hence, you can quote many different things. For example, you can even quote Scheme expressions.
> '(+ 2 3) '(+ 2 3) > (quote (* 2 3)) '(* 2 3)
Although you can use quote in a variety of ways, we prefer that you limit your use to quoting symbolic values, at least for the first few weeks of class. Our experience shows that those who quote other kinds of values early in the course end up with confusing results later in the course.
Check 1: Data types
Which of the following expressions is a name for a Scheme value? Which is a symbol? Which is a string?
``` “pi” pi ‘pi
Check 2: Operations on symbols
Make a list of the operations that you’ve seen so far that take a symbol as an argument or that generate a symbol as a result. Are there others that might be useful?