S-expressions As Lisp Forms
After the reader has translated a bunch of text into s-expressions, the s-expressions can then be evaluated as Lisp code. Or some of them can—not every s-expressions that the reader can read can necessarily be evaluated as Lisp code. Common Lisp’s evaluation rule defines a second level of syntax that determines which s-expressions can be treated as Lisp forms.9 The syntactic rules at this level are quite simple. Any atom—any nonlist or the empty list—is a legal Lisp form as is any list that has a symbol as its first element.10
Of course, the interesting thing about Lisp forms isn’t their syntax but how they’re evaluated. For purposes of discussion, you can think of the evaluator as a function that takes as an argument a syntactically well-formed Lisp form and returns a value, which we can call the value of the form. Of course, when the evaluator is a compiler, this is a bit of a simplification—in that case, the evaluator is given an expression and generates code that will compute the appropriate value when it’s run. But this simplification lets me describe the semantics of Common Lisp in terms of how the different kinds of Lisp forms are evaluated by this notional function.
The simplest Lisp forms, atoms, can be divided into two categories: symbols and everything else. A symbol, evaluated as a form, is considered the name of a variable and evaluates to the current value of the variable.11 I’ll discuss in Chapter 6 how variables get their values in the first place. You should also note that certain “variables” are that old oxymoron of programming: “constant variables.” For instance, the symbol **PI**
names a constant variable whose value is the best possible floating-point approximation to the mathematical constant pi.
All other atoms—numbers and strings are the kinds you’ve seen so far—are self-evaluating objects. This means when such an expression is passed to the notional evaluation function, it’s simply returned. You saw examples of self-evaluating objects in Chapter 2 when you typed 10
and "hello, world"
at the REPL.
It’s also possible for symbols to be self-evaluating in the sense that the variables they name can be assigned the value of the symbol itself. Two important constants that are defined this way are **T**
and **NIL**
, the canonical true and false values. I’ll discuss their role as booleans in the section “Truth, Falsehood, and Equality.”
Another class of self-evaluating symbols are the keyword symbols—symbols whose names start with :
. When the reader interns such a name, it automatically defines a constant variable with the name and with the symbol as the value.
Things get more interesting when we consider how lists are evaluated. All legal list forms start with a symbol, but three kinds of list forms are evaluated in three quite different ways. To determine what kind of form a given list is, the evaluator must determine whether the symbol that starts the list is the name of a function, a macro, or a special operator. If the symbol hasn’t been defined yet—as may be the case if you’re compiling code that contains references to functions that will be defined later—it’s assumed to be a function name.12 I’ll refer to the three kinds of forms as function call forms, macro forms, and special forms.