LISP-tutorial.txt

(29 KB) Pobierz
                          Common LISP Hints
                          Geoffrey J. Gordon
                         <ggordon@cs.cmu.edu>
                       Friday, February 5, 1993

                            Modified by
                            Bruno Haible
                <haible@ma2s2.mathematik.uni-karlsruhe.de>

Note: This tutorial introduction to Common Lisp was written for the
CMU environment, so some of the details of running lisp toward the end
may differ from site to site.


Further Information

The best LISP textbook I know of is

  Guy L. Steele Jr. _Common LISP: the Language_. Digital Press. 1984.

The first edition is easier to read; the second describes a more recent
standard. (The differences between the two standards shouldn't affect
casual programmers.)

A book by Dave Touretsky has also been recommended to me, although I
haven't read it, so I can't say anything about it.



Symbols

A symbol is just a string of characters. There are restrictions on what
you can include in a symbol and what the first character can be, but as
long as you stick to letters, digits, and hyphens, you'll be safe.
(Except that if you use only digits and possibly an initial hyphen,
LISP will think you typed an integer rather than a symbol.) Some
examples of symbols:

        a
        b
        c1
        foo
        bar
        baaz-quux-garply

Some things you can do with symbols follow. (Things after a ">" prompt
are what you type to the LISP interpreter, while other things are what
the LISP interpreter prints back to you. The ";" is LISP's comment
character: everything from a ";" to the end of line is ignored.)

> (setq a 5)            ;store a number as the value of a symbol
5
> a                     ;take the value of a symbol
5
> (let ((a 6)) a)       ;bind the value of a symbol temporarily to 6
6
> a                     ;the value returns to 5 once the let is finished
5
> (+ a 6)               ;use the value of a symbol as an argument to a function
11
> b                     ;try to take the value of a symbol which has no value
Error: Attempt to take the value of the unbound symbol B

There are two special symbols, t and nil. The value of t is defined
always to be t, and the value of nil is defined always to be nil. LISP
uses t and nil to represent true and false. An example of this use is
in the if statement, described more fully later:

> (if t 5 6)
5
> (if nil 5 6)
6
> (if 4 5 6)
5

The last example is odd but correct: nil means false, and anything else
means true. (Unless we have a reason to do otherwise, we use t to mean
true, just for the sake of clarity.)

Symbols like t and nil are called self-evaluating symbols, because
they evaluate to themselves. There is a whole class of self-evaluating
symbols called keywords; any symbol whose name starts with a colon is a
keyword. (See below for some uses for keywords.) Some examples:

> :this-is-a-keyword
:THIS-IS-A-KEYWORD
> :so-is-this
:SO-IS-THIS
> :me-too
:ME-TOO



Numbers

An integer is a string of digits optionally preceded by + or -. A real
number looks like an integer, except that it has a decimal point and
optionally can be written in scientific notation. A rational looks like
two integers with a / between them. LISP supports complex numbers,
which are written #c(r i) (where r is the real part and i is the
imaginary part). A number is any of the above. Here are some numbers:

        5
        17
        -34
        +6
        3.1415
        1.722e-15
        #c(1.722e-15 0.75)

The standard arithmetic functions are all available: +, -, *, /, floor,
ceiling, mod, sin, cos, tan, sqrt, exp, expt, and so forth. All of them
accept any kind of number as an argument. +, -, *, and / return a
number according to type contagion: an integer plus a rational is a
rational, a rational plus a real is a real, and a real plus a complex
is a complex. Here are some examples:

> (+ 3 3/4)             ;type contagion
15/4
> (exp 1)               ;e
2.7182817
> (exp 3)               ;e*e*e
20.085537
> (expt 3 4.2)          ;exponent with a base other than e
100.90418
> (+ 5 6 7 (* 8 9 10))  ;the fns +-*/ all accept multiple arguments

There is no limit to the absolute value of an integer except the memory
size of your computer. Be warned that computations with bignums (as
large integers are called) can be slow. (So can computations with
rationals, especially compared to the corresponding computations with
small integers or floats.)



Conses

A cons is just a two-field record. The fields are called "car" and
"cdr", for historical reasons. (On the first machine where LISP was
implemented, there were two instructions CAR and CDR which stood for
"contents of address register" and "contents of decrement register".
Conses were implemented using these two registers.)

Conses are easy to use:

> (cons 4 5)            ;Allocate a cons. Set the car to 4 and the cdr to 5.
(4 . 5)
> (cons (cons 4 5) 6)
((4 . 5) . 6)
> (car (cons 4 5))
4
> (cdr (cons 4 5))
5



Lists

You can build many structures out of conses. Perhaps the simplest is a
linked list: the car of each cons points to one of the elements of the
list, and the cdr points either to another cons or to nil. You can
create such a linked list with the list fuction:

> (list 4 5 6)
(4 5 6)

Notice that LISP prints linked lists a special way: it omits some of
the periods and parentheses. The rule is: if the cdr of a cons is nil,
LISP doesn't bother to print the period or the nil; and if the cdr of
cons A is cons B, then LISP doesn't bother to print the period for cons
A or the parentheses for cons B. So:

> (cons 4 nil)
(4)
> (cons 4 (cons 5 6))
(4 5 . 6)
> (cons 4 (cons 5 (cons 6 nil)))
(4 5 6)

The last example is exactly equivalent to the call (list 4 5 6). Note
that nil now means the list with no elements: the cdr of (a b), a list
with 2 elements, is (b), a list with 1 element; and the cdr of (b), a
list with 1 element, is nil, which therefore must be a list with no
elements.

The car and cdr of nil are defined to be nil.

If you store your list in a variable, you can make it act like a stack:

> (setq a nil)
NIL
> (push 4 a)
(4)
> (push 5 a)
(5 4)
> (pop a)
5
> a
(4)
> (pop a)
4
> (pop a)
NIL
> a
NIL



Functions

You saw one example of a function above. Here are some more:

> (+ 3 4 5 6)                   ;this function takes any number of arguments
18
> (+ (+ 3 4) (+ (+ 4 5) 6))     ;isn't prefix notation fun?
22
> (defun foo (x y) (+ x y 5))   ;defining a function
FOO
> (foo 5 0)                     ;calling a function
10
> (defun fact (x)               ;a recursive function
    (if (> x 0)
      (* x (fact (- x 1)))
      1))
FACT
> (fact 5)
120
> (defun a (x) (if (= x 0) t (b (- x))))        ;mutually recursive functions
A
> (defun b (x) (if (> x 0) (a (- x 1)) (a (+ x 1))))
B
> (a 5)
T
> (defun bar (x)                ;a function with multiple statements in
    (setq x (* x 3))            ;its body -- it will return the value
    (setq x (/ x 2))            ;returned by its final statement
    (+ x 4))
BAR
> (bar 6)
13

When we defined foo, we gave it two arguments, x and y. Now when we
call foo, we are required to provide exactly two arguments: the first
will become the value of x for the duration of the call to foo, and the
second will become the value of y for the duration of the call. In
LISP, most variables are lexically scoped; that is, if foo calls bar
and bar tries to reference x, bar will not get foo's value for x.

The process of assigning a symbol a value for the duration of some
lexical scope is called binding.

You can specify optional arguments for your functions. Any argument
after the symbol &optional is optional:

> (defun bar (x &optional y) (if y x 0))
BAR
> (defun baaz (&optional (x 3) (z 10)) (+ x z))
BAAZ
> (bar 5)
0
> (bar 5 t)
5
> (baaz 5)
15
> (baaz 5 6)
11
> (baaz)
13

It is legal to call the function bar with either one or two arguments.
If it is called with one argument, x will be bound to the value of that
argument and y will be bound to nil; if it is called with two
arguments, x and y will be bound to the values of the first and second
argument, respectively.

The function baaz has two optional arguments. It specifies a default
value for each of them: if the caller specifies only one argument, z
will be bound to 10 instead of to nil, and if the caller specifies no
arguments, x will be bound to 3 and z to 10.

You can make your function accept any number of arguments by ending its
argument list with an &rest parameter. LISP will collect all arguments
not otherwise accounted for into a list and bind the &rest parameter to
that list. So:

> (defun foo (x &rest y) y)
FOO
> (foo 3)
NIL
> (foo 4 5 6)
(5 6)

Finally, you can give your function another kind of optional argument
called a keyword argument. The caller can give these arguments in any
order, because they're labelled with keywords.

> (defun foo (&key x y) (cons x y))
FOO
> (foo :x 5 :y 3)
(5 . 3)
> (foo :y 3 :x 5)
(5 . 3)
> (foo :y 3)
(NIL . 3)
> (foo)
(NIL)

An &key parameter can have a default value too:

> (defun foo (&key (x 5)) x)
FOO
> (foo :x 7)
7
> (foo)
5



Printing

Some functions can cause output. The simplest one is print, which
prints its argument and then returns it.

> (print 3)
3
3

The first 3 above was printed, the second was returned.

If you want more complicated output, you will need to use format.
Here's an example:

> (format t "An atom: ~S~%and a list: ~S~%and an integer: ~D~%"
          nil (list 5) 6)
An atom: NIL
and a list: (5)
and an integer: 6

The first argument to format is either t, nil, or a stream. ...
Zgłoś jeśli naruszono regulamin