Common lisp first steps beginner tutorial - wikibooks, open books for an open world
- 6. 4/14/2015 Common Lisp/First steps/Beginner tutorial Wikibooks, open books for an open world
http://en.wikibooks.org/wiki/Common_Lisp/First_steps/Beginner_tutorial 6/19
This works OK in practice. A calculation such as 6×5×4/(3×2×1) gets translated to the following piece of
Lisp:
(/ (* 6 5 4) 3 2 1)
Binding
Binding is the act of specifying a place holder for a value. The concept is analogous to that of a local
variable in C or Java. You often want to do this because it is cumbersome to write out long expressions
multiple times, or if a computation needs to be done in small parts where a binding needs to be updated at
various times during execution. The main way to create bindings is via the “special form” LET.
(let ((5‐squared (* 5 5))
(10‐squared (* 10 10)) )
(* 5‐squared 10‐squared) )
Here, 5SQUARED and 10SQUARED are place holders ("local variables") for the results of the
calculation (* 5 5) and (* 10 10), respectively. It is good to note at this time that there are very few rules
regarding what can be used as a place holder. These place holders are called symbols and it can have a
name that includes most any characters with the exception of quotes, open or close parenthesis, colons,
backslashes, or vertical bars (‘|’). These all have special syntactical meaning in Common Lisp. It is good to
note that all of these things actually can be in the name of a symbol but they require special escaping.
Bindings have a limited scope. Once the LET form closes, the binding is invalidated. This means that this is
an error, because a is referred to outside of the enclosing LET form.
(let ((a (sqrt 100))))
(print a)
It is interesting to note the behavior if you bind a symbol that has already been bound. Once the inner
binding is released, the outer one is in effect again.
(let ((a 1))
(print a)
(let ((a 2))
(print a) )
(print a) )
==> 1
2
1
- 7. 4/14/2015 Common Lisp/First steps/Beginner tutorial Wikibooks, open books for an open world
http://en.wikibooks.org/wiki/Common_Lisp/First_steps/Beginner_tutorial 7/19
The story gets a bit more complex, there are two types of way to make bindings in Common Lisp, lexical,
which we have just seen, and dynamic. For our purposes at this point, dynamic bindings are not much
different from lexical bindings, but they are made in a different way and do not have the same finite extent
of the LET form. We can use DEFVAR and DEFPARAMETER to make dynamic bindings. These can hold
a value in between inputs.
(defvar a 5)
(print a)
(let ((a 10))
(print a) )
(print a)
==> a
5
10
5
Variables
In Lisp, variables have some extra features, and are called symbols. A variable is a box containing a value.
A symbol is a somewhat larger box, with its name written on the side. A symbol has two values, a general
purpose value, and a function value used instead in particular circumstances. You can use the symbol as a
thing in itself, without regard to its value.
setf
We start by setting a symbol's general purpose value. There are several commands for setting the values of
symbols, set, setq, setf, psetq, psetf. One can get a long way with just setf so we start with that one
(setf my‐first‐symbol 57)
57
This sets the general purpose value of the symbol MYFIRSTSYMBOL to 57, and returns 57. Now we can
type
my‐first‐symbol
57
and
(+ my‐first‐symbol 3)
60
- 8. 4/14/2015 Common Lisp/First steps/Beginner tutorial Wikibooks, open books for an open world
http://en.wikibooks.org/wiki/Common_Lisp/First_steps/Beginner_tutorial 8/19
(setf second‐symbol (+ 20 3))
23
Well, plainly this has performed the calculation, and returned the answer, but what did the general purpose
value of our secondsymbol get set to? Have we used it to record the calculation we requested, (+ 20 3), or
the answer that the computer calculated?
second‐symbol
23
If we want to record the calculation for future reference we must "quote" it. Think of the computer as a
horse and the quote as a bridle, reining it in, stopping it from rushing on to evaluate things before you want
it to.
(setf third (quote (+ 20 3)))
(+ 20 3)
Now
third
(+ 20 3)
the general purpose value of our third symbol contains a calculation, which the computer is champing at the
bit to execute.
eval
If quote pulls on the reins, how do we get started again? The answer: eval.
(eval third)
23
It is controversial to use quote in the first lesson because it is seldom typed in explicitly. One types
(setf third '(+ 20 3))
(+ 20 3)
Notice that this is a very special abbreviation. Not only are the five letters of quote shortened to the single
character ', but the brackets are also omitted. It should be noted that when we use a lisp interpreter, we are
essentially in an infinite READEVALPRINT loop. Thus, we are really using eval all the time.
list
We have set three symbols so far and are perhaps in danger of forgetting what they contain. The function
list builds a list, e.g.
- 13. 4/14/2015 Common Lisp/First steps/Beginner tutorial Wikibooks, open books for an open world
http://en.wikibooks.org/wiki/Common_Lisp/First_steps/Beginner_tutorial 13/19
(* 2 3)
6
only looks like it is doing what you think. It is evaluating 2 and 3, getting 2 and 3 as the results of the two
evaluations, then multiplying the two results to get six.
When the interpreter evaluates (+ 1 (* 2 3)) it evaluates 1 and (* 2 3). 1 evaluates to 1, (* 2 3) evaluates to
6. Then it adds them to get 7.
There is something worth pondering here. Get a cheap, old, pocket calculator out of a drawer and try 1 + 2
x 3 Typically, when you press x, the calculator, lacking an extra register to hold pending results, carries out
the addition of the one and the two. One ends up calculating 3 x 3 and getting 9, rather than 7. Modern
calculators follow the standard rules of precedence, and defer performing the addition until after they have
multiplied 2 by 3, eventually arriving at 7, as desired.
Computer languages have many more operations than addition and multiplication and often have elaborate
systems of precedence controlling which operations are carried out first. Lisp has no such subtlety. One
either writes
(1+2)x3 as
(* (+ 1 2) 3)
or one writes
1+(2x3) as
(+ 1 (* 2 3))
there is no way to preserve the ambiguity of 1+2x3
This turns out to be for the best in practice.
Obscure note: You could try (+ 1 * 2 3). At the top level, * is used for recalling the result of the previous
command. If that was a number it will give the wrong answer. If that was not a number the interpreter will
signal an error. Within a program, (+ 1 * 2 3) will generate an error message saying that * has no value.
More on this later.
Let us return to third. Remember that we set our third symbol to a list of three items. We can see the whole
list by typing third
third
(+ 20 3)
Lisp has functions for extracting items from a list. First gets the first item
(first third)