Symbols and little tables
Names used as plain data, the difference between comparing identity and comparing contents, and tables built from pairs.
A name that is only a name
A symbol is a name used as a value. Written plainly, ada would be looked up — Scheme would try to find what it names. Written as (quote ada) it is just the symbol itself, and the quote is what stops the lookup. The shorthand is an apostrophe before the name: 'ada, with no brackets at all.
Symbols are cheap, they compare instantly, and they print without quotes or brackets. That makes them the natural keys for a small table: readable in the source, readable in the output, and impossible to confuse with the text a user typed, which would arrive as a string.
The same value, or the same object
eq? asks whether two values are the very same object. equal? is the friendlier question: it walks two values and asks whether their contents match. Two lists built separately hold equal contents but are not the same object, so eq? says no and equal? says yes.
For symbols, identity is guaranteed: two occurrences of (quote ada) are the same symbol, so eq? is a fast yes. That is why symbol tables use the faster lookup, while string keys need the slower content comparison.
A table is a list of pairs
Scheme has no dictionary type in the core language, and it does not need one: a list of pairs is a table. Each entry is built with cons, with the key on the left and the value on the right, and assoc finds the entry whose key matches.
The answer from assoc is the whole pair, so (cdr (assoc ...)) is how you get the value out. When the key is not in the table the answer is #f, which is worth checking for before you take the pair apart.
Reading a symbol, and quoting a list
The reader turns text into data before anything is evaluated. ada becomes a symbol, "ada" becomes a string, and (a b) becomes a list of two symbols. Quote tells the evaluator to hand that data back unchanged.
That is why (quote (1 2)) and (list 1 2) look the same when printed but are built differently. The first is literal data; the second calls list at run time. For symbols the difference matters less, but for a table of fixed keys the quoted form says what you mean.
symbol? recognises the result, and symbol->string converts it when you need text. A symbol is not a variable: it has no value slot, which is exactly why it makes a stable key.
Choosing the comparison
eq? is the cheapest question: are these two the same object? For symbols the answer is reliable, because the reader creates one symbol per spelling. For lists and strings it is not the question you usually mean.
equal? walks the structure and compares contents. It is the right test for two lists, two strings, or a record you built twice. It costs more, and it is almost always what a program means.
assq uses eq?, so it is the fast lookup for symbol keys. assoc uses equal?, so it works for strings and lists. Pick the table function that matches the key type, or a lookup will miss for a reason that looks like a bug in the data.
Symbols, equality and a table
(print (quote ada))
(print (equal? (quote ada) (quote ada)))
(print (equal? "ada" "ada"))
; A record: three values in a list.
(define ada (list "Ada" 36 "London"))
(print (car ada))
(print (list-ref ada 1))
(print (cdr ada))
; A table of keys and values.
(define table (list (cons (quote a) 1)
(cons (quote b) 2)))
(print (cdr (assq (quote b) table)))
(print (assq (quote z) table))Quoted data is still data
A quoted list is a value you can take apart with car and cdr like any other list. The quote only stops the evaluator from treating the first item as an operation. (car (quote (a b))) answers the symbol a, and (cdr (quote (a b))) answers (b), with no lookup of a or b anywhere.
That is why a table of fixed keys is often written as a quoted list of pairs, and why the same structure can be built with cons when the keys are computed. The two forms print alike; the difference is when the structure was made.
Three mistakes with quoted data. Writing (quote ada) where you meant the value of a variable named ada gives you the symbol instead. Quoting a whole expression stops it from running, so (quote (+ 1 2)) is three items, not 3. And assq is the wrong lookup for string keys.
Try these next
- Build a table with three symbol keys and print every key with
mapandcar. - Look up a key that is missing with both
assqandassocand compare the answers. - Print
(symbol? (quote hello))and(symbol? "hello").
A phone table
Run it and read the eight lines. Then add yourself to the table, look yourself up, and print every key in the book with `map` and `car`.
Two tables, two kinds of key
Run it and compare the two lookups. Then add a third city with a string key, and look it up with `assoc`.
Use assq when the keys are symbols: the comparison is an identity check, so it is quick, and it cannot be fooled. Reach for assoc when the keys are strings or lists, because those have to be compared by their contents.
Check what you learned
One question at a time. A wrong answer explains itself — take another go.
Part 1 of 5
What does (quote ada) give?
