Basic LISP Programming Common LISP follows the algorithm below when interacting with users: loop read in an expression from the console; evaluate the expression; print the result of evaluation end loop.
Sample Session (* 2 (cos 0) (+ 4 6)) 20.0 (defun double (x) (* x 2)) DOUBLE (double 3) 6
This is a program typed into a text file ;; Triple the value of a number ;; (defun triple (X) "Compute three times X." ; Inline comments can (* 3 X)) ; be placed here. ;; ;; Negate the sign of a number ;; (defun negate (X) "Negate the value of X." ; This is a comment (- X))
Name the file testing.lisp. Now load the definition into the LISP environment by typing: > (load "testing.lisp") T
Recursions and Conditionals We can implement a function to compute factorials using recursion: (defun factorial (N) ;; Compute the factorial of N. (if (= N 1) 1 (* N (factorial (- N 1))))) Note: LISP treats NIL as false, and everything else as true.
Relational Operators
The Trace Function (trace factorial) (FACTORIAL) USER(12): (factorial 4) 0: (FACTORIAL 4) 1: (FACTORIAL 3) 2: (FACTORIAL 2) 3: (FACTORIAL 1) 3: returned 1 2: returned 2 1: returned 6 0: returned 24 24
Recall the definition of Fibonacci numbers: Fib(n) = 1 for n = 0 or n = 1 Fib(n) = Fib(n-1) + Fib(n-2) for n > 1 LISP code: (defun fibonacci (N) ;; Compute the N'th Fibonacci number (if (or (zerop N) (= N 1)) 1 (+ (fibonacci (- N 1)) (fibonacci (- N 2)))))
Built-in Shorthands and Predicates
The or form logical operator It evaluates its arguments from left to right, returning non-NIL immediately if it encounters an argument that evaluates to non- NIL. It evaluates to NIL if all tests fail.
Logical Operators
Lists (cons 1 (cons 2 nil)) (1 2) (quote ( )) ( ) '( ) ( )
Your session may look more like this: USER(24): (first '(2 4 8)) 2 USER(25): (rest '(2 4 8)) (4 8) USER(26): (first (rest '(2 4 8))) 4 USER(27): (rest (rest '(2 4 8))) (8) USER(28): (rest (rest (rest '(8)))) NIL
Recognizers Corresponding to each constructor of a data type is a recognizer. In the case of list, they are null for nil and consp for cons. Given a list L, (null L) returns t iff L is nil and (consp L) returns t iff L is constructed from cons.
USER(29): (null nil) T USER(30): (null '(1 2 3)) NIL USER(31): (consp nil) NIL USER(32): (consp '(1 2 3)) T
recursive functions that traverse a list. The LISP built-in function list-length counts the number of elements in a list. USER(33): (list-length '( )) 8
we could implement our own version of list- length as follows: (defun recursive-list-length (L) (if (null L) 0 (1+ (recursive-list-length (rest L)))))
Symbols USER(45): 'a ; LISP is case-insensitive. A USER(46): 'A ; 'a and 'A evaluate to the same symbol. A USER(47): 'apple2 ; Both alphanumeric characters... APPLE2 USER(48): 'an-apple ;... and symbolic characters are allowed. AN-APPLE USER(49): t ; Our familiar t is also a symbol. T USER(50): 't ; In addition, quoting is redundant for t. T USER(51): nil ; Our familiar nil is also a symbol. NIL USER(52): 'nil ; Again, it is self-evaluating. NIL
With symbols, we can build more interesting lists: USER(53): '(how are you today ?) ; A list of symbols. (HOW ARE YOU TODAY ?) USER(54): '(1 + 2 * x) ; A list of symbols and numbers. (1 + 2 * X) USER(55): '(pair (2 3)) ; A list containing 'pair and '(2 3). (pair (2 3)) Notice that the list (pair (2 3)) has length 2:
Example: nth LISP defines a function (nth N L) that returns the N'th member of list L (assuming that the elements are numbered from zero onwards): USER(59): (nth 0 '(a b c d)) A USER(60): (nth 2 '(a b c d)) C