Special Operators
That said, not all operations can be defined as functions. Because all the arguments to a function are evaluated before the function is called, there’s no way to write a function that behaves like the **IF**
operator you used in Chapter 3. To see why, consider this form:
(if x (format t "yes") (format t "no"))
If **IF**
were a function, the evaluator would evaluate the argument expressions from left to right. The symbol x
would be evaluated as a variable yielding some value; then (format t "yes")
would be evaluated as a function call, yielding **NIL**
after printing “yes” to standard output. Then (format t "no")
would be evaluated, printing “no” and also yielding **NIL**
. Only after all three expressions were evaluated would the resulting values be passed to **IF**
, too late for it to control which of the two **FORMAT**
expressions gets evaluated.
To solve this problem, Common Lisp defines a couple dozen so-called special operators, **IF**
being one, that do things that functions can’t do. There are 25 in all, but only a small handful are used directly in day-to-day programming.13
When the first element of a list is a symbol naming a special operator, the rest of the expressions are evaluated according to the rule for that operator.
The rule for **IF**
is pretty easy: evaluate the first expression. If it evaluates to non-**NIL**
, then evaluate the next expression and return its value. Otherwise, return the value of evaluating the third expression or **NIL**
if the third expression is omitted. In other words, the basic form of an **IF**
expression is as follows:
(if test-form then-form [ else-form ])
The test-form will always be evaluated and then one or the other of the then-form or else-form.
An even simpler special operator is **QUOTE**
, which takes a single expression as its “argument” and simply returns it, unevaluated. For instance, the following evaluates to the list (+ 1 2)
, not the value 3:
(quote (+ 1 2))
There’s nothing special about this list; you can manipulate it just like any list you could create with the **LIST**
function.14
**QUOTE**
is used commonly enough that a special syntax for it is built into the reader. Instead of writing the following:
(quote (+ 1 2))
you can write this:
'(+ 1 2)
This syntax is a small extension of the s-expression syntax understood by the reader. From the point of view of the evaluator, both those expressions will look the same: a list whose first element is the symbol **QUOTE**
and whose second element is the list (+ 1 2)
.15
In general, the special operators implement features of the language that require some special processing by the evaluator. For instance, several special operators manipulate the environment in which other forms will be evaluated. One of these, which I’ll discuss in detail in Chapter 6, is **LET**
, which is used to create new variable bindings. The following form evaluates to 10 because the second x
is evaluated in an environment where it’s the name of a variable established by the **LET**
with the value 10:
(let ((x 10)) x)