A form can be either an atom or a list. The important thing is that the form is meant to be evaluated. Evaluation has a fairly technical definition that we'll gradually expose in this section.
Evaluation is simple if the form is an atom. Lisp treats the atom as a name, and retrieves the value for the name (if a value exists). You probably wonder why I'm avoiding the more direct explanation of calling the atom a variable. The reason is that the atom can have either a variable value or a constant value. And the atom's value can be constant for a couple of reasons.
A number is an atom. (Its value is constant for obvious reasons.) Lisp does not store a value for a number -- the number is said to be self-evaluating.
We're going to introduce a new term without a complete definition. For now, think of a symbol as an atom that can have a value. We'll look at symbols in greater detail when we get to Lesson 5.
A symbol defined in a
defconstant form has a constant
value. Lisp will store the value as if the atom had a variable value, and
add a note to the effect that the value is not allowed to change.
A symbol in the
KEYWORD package is self-evaluating. We'll
look at packages in detail in Chapter 31. For
now, all you need to know is that a symbol beginning with the
character (called the package prefix) is a keyword symbol. Keyword
symbols have themselves as their values.
A symbol can get a variable value in many different ways. Lisp actually keeps several different values for a symbol. One has the traditional meaning as the value of the symbol taken as a variable. Another has meaning as the symbol's function. Still others keep track of the symbol's documentation, its printed representation, and properties that the programmer chooses to associate with the symbol. We'll explore some of these in more detail in Lesson 5, Lesson 6, and Lesson 7.
If a form is a list, then the first element must be either a symbol or a
special form called a lambda expression. (We won't look at lambda
expressions for a while.) The symbol must name a function. In Lisp, the
/ name the four common arithmetic operations: addition,
subtraction, multiplication, and division. Each of these symbols has an
associated function that performs the arithmetic operation.
So when Lisp evaluates the form
(+ 2 3), it applies the
function for addition to the arguments
giving the expected result
5. Notice how the function symbol,
+, precedes its arguments. This is prefix
notation. Any time you see a list, look to its first element to find out
what Lisp will do to evaluate the list as a form.
Lisp, when given a list to evaluate, treats the form as a function call. We'll be looking a lot at Lisp evaluation from now on, so we'll use some visual aids to identify the input to Lisp and its responses:
the Lisp prompt precedes input to Lisp
result of Lisp evaluation
(+ 4 9)
(- 5 7)
(* 3 9)
(/ 15.0 2)
In each case above, the evaluated form is a list. Its first element is a symbol, which names a function. The remaining elements are arguments of the function. Here, the arguments are all numbers, and we know that numbers are self-evaluating.
Here are a few more examples:
NUMBERP are predicates. Predicates
return a true or false value.
NIL is the only false value in
Lisp -- everything else is true. Unless a predicate has a more useful
value to return, it conventionally returns
T to mean true.
T if its one argument is a Lisp atom.
T if its argument is a number.
To evaluate each of the above forms, Lisp first evaluates the arguments (from left to right), then evaluates the first element to get its function, then applies the function to the arguments. With only a handful of exceptions, which we'll learn about at the end of this lesson, Lisp always does the same thing to evaluate a list form:
Remember that an atom can also be a Lisp form. When given an atom to evaluate, Lisp simply returns its value:
(:ANSI-CL :CLOS :COMMON-LISP)
Error: Unbound variable
Numbers and keywords are self-evaluating. So are strings. The
*FEATURES* variable is predefined by Lisp -- your system will
probably return a different value.
WHAT-IS-THIS? doesn't have a value, because it's
not predefined by Lisp, and I haven't given it a value. The system
responds with an error message, rather than a value. We mark the message
rather than the
marker we use for successful evaluations. Your system will probably print
a different message.
Sometimes you'd like to have a function return several values. For example, a function which looks up a database entry might return both the desired result and a completion status code. One way to do this is to pass to the function a location for one of the results; this is possible, but very uncommon for a Lisp program.
Another approach creates a single return value to combine both the result and the status code. Lisp gives you several different ways to do this, including structures. Experienced Lisp programmers don't do this when the created value will just be taken apart into its components and then forgotten, since the composite value then becomes garbage (see Chapter 29) that eventually slows down the operation of the program.
The right way to return multiple values from a function is to use the
VALUES form. We'll see
VALUES used in the context of a
function in a little while. For now, let's see what happens when Lisp
(values 1 2 3 :hi "Hello")
Notice how Lisp returned a value (following the indicator) for
each argument to the
VALUES form. My Lisp system
represents this by printing each value on a new line; yours may separate
the values some other way.
I mentioned earlier that you can pass a location to a function, and have the function change the location's value. This is a very uncommon practice for a Lisp program, even though other languages make it part of their standard repertoire.
You could specify the location to be modified as either a non-keyword symbol or a composite value -- obviously, you can't modify a constant. If you provide a symbol, then your function must execute code to give the symbol a new value. If you provide a composite data structure, your function must execute code to change the correct piece of the composite value. It's harder to write Lisp code to do this, and it's harder to understand programs written this way. So Lisp programmers usually write functions that get their inputs from parameters, and produce their outputs as the function result.
When Lisp evaluates a function, it always evaluates all the arguments first, as we saw earlier. Unfortunately, every rule has exceptions, and this rule is no exception (as we'll soon see)... The problem is not that Lisp doesn't always evaluate a function's arguments, but that not every list form is a function call.
When a list form is a function call, its arguments are always evaluated in order, from left to right. As in other programming languages, it's in poor taste to rely on this, but if you absolutely have to rely on the order, it's good to know that Lisp defines it for you.
So if a list form isn't always a function call, what else can it be? There are two cases, but the result is the same: some arguments are evaluated, and some aren't. Which is which depends upon the form and nothing else. You'll just have to learn the exceptions. Fortunately, most Lisp systems will show you the online documentation for any form with just a keystroke or two.
There are two kinds of forms that don't evaluate all of their arguments: special forms and macros. Lisp predefines a small number of special forms. You can't add your own special forms -- they're primitive features of the language itself. Lisp also defines quite a few macros. You can also define your own macros. Macros in Lisp let you use the full power of the language to add your own features. Later in this chapter we'll look briefly at how to define simple macros. In Chapter 20 we'll cover topics surrounding the creation of more complex macros.