CS 451 Programming Paradigms
LISP Basics Tutorial


Login to one of badshot, thelma, or shaggy on the CS network.
  If you are on CIRT, you may have to do something first to get to the CS network.

Once on CS, to login to, say badshot, you type:

  ssh badshot

	It may ask you if you want to add this to the list of hosts.  If it does
	type the WHOLE WORD "yes" and hit enter

	Then you will have to type your password.

Once on shaggy, badshot, or thelma
  you should cd to the directory where you wish to work or where the LISP code
	that you wish to work on is already located

Once there simply type  cl

You will see:

Allegro CL 4.3 [Linux/X86; R1] (8/26/98 12:09)
Copyright (C) 1985-1996, Franz Inc., Berkeley, CA, USA.  All Rights Reserved.
;; Optimization settings: safety 1, space 1, speed 1, debug 2.
;; For a complete description of all compiler switches given the
;; current optimization settings evaluate (EXPLAIN-COMPILER-SETTINGS).



;From here on out are examples of LISP expressions that you should understand.
;Anything after "USER(X):", including stuff indented on subsequent lines,
;is typed to the interpreter.
;Anything that follows the indented stuff before the next "USER(X)" prompt
;is the reponse of the interpreter to the preceding expression.


;Sometimes you will see text describing what's important about the example.
;Like each of these lines, these will be preceded by a semicolon, 
;the line-comment character in LISP.



USER(1): (print "everything in lisp is prefix")

"everything in lisp is prefix"
"everything in lisp is prefix"

USER(2): (+ 2 3)
5
USER(3): (* (+ 2 3) -4)
-20


USER(4): (print "binding free variables")

"binding free variables"
"binding free variables"

USER(5): (setq x 5)
5
USER(6): (setq a '(q 1 2 z))
(Q 1 2 Z)
USER(7): x
5
USER(8): a
(Q 1 2 Z)
USER(9): (car '(b c 5 9))
B
USER(10): (car a)
Q
USER(11): (cdr '(b c 5 9))
(C 5 9)
USER(12): (cdr a)
(1 2 Z)
USER(13): (car (cdr a))
1
USER(14): (cadr a)
1
USER(15): (caddr a)
2
USER(16): (cadddr a)
Z
USER(17): (setq b '( (1 2) z (q 9) (a (b c) d) ))
((1 2) Z (Q 9) (A (B C) D))
USER(18): (car (cdr (cdr (cdr b))))
(A (B C) D)
USER(19): (car (car (cdr (cdr (cdr b)))))
A

;There is a limit to the size of these 'abbreviations'


USER(20): (caadddr b)
Error: attempt to call `CAADDDR' which is an undefined function.
[condition type: UNDEFINED-FUNCTION]

Restart actions (select using :continue):
0: Try calling CAADDDR again.
1: Return a value instead of calling CAADDDR.
2: Try calling a function other than CAADDDR.
3: Setf the symbol-function of CAADDDR and call it again.
[1] USER(21): (caaddr (cdr b))
A                                                    

[1] USER(22): (cdr '(a))
NIL
[1] USER(23): (car '((a)))
(A)
[1] USER(24): (cdr '(1 2))
(2)
[1] USER(25): (cons 'a '(b c))
(A B C)


;what happens if you use cons with a non-list second argument?
;you get a dotted pair:

<prompt>: (cons 'a 'b)
(a . b)

;We don't want to worry about these.  So don't do that


[1] USER(26): (setq x (cons '1 '(2)))
(1 2)
[1] USER(27): (car x)
1
[1] USER(28): (cdr x)
(2)
[1] USER(29): (cadr x)
2
[1] USER(30): (nth 2 x)
NIL
[1] USER(31): (nth 1 x)
2
[1] USER(32): (cons '(a b) '(c d))
((A B) C D)
[1] USER(33): (cons 'a nil)
(A)
[1] USER(34): x
(1 2)
[1] USER(35): (cons (car x) (cons (cadr x) '(3 4)))
(1 2 3 4)
[1] USER(36): x
(1 2)

;Note the difference between setq and setf:
<prompt>: (setq z 5)
5
<prompt>: z
5
<prompt>: (setf (cadr x) 5)  ;x defined as (1 2) above
5
<prompt>: x
(1 5)

;;DANGEROUS!!!




[1] USER(37): (print "cons is nondestructive!!")

"cons is nondestructive!!"
"cons is nondestructive!!"

;This means that when a cons call creates a new list containing
;variables bound to other things, those other things are not
;changed by the cons call

[1] USER(38): (list '1 '2 '3 '(4 5))
(1 2 3 (4 5))
[1] USER(39): (append '(1) '(2 3) '(4 5))   ;MUST BE LISTS
(1 2 3 4 5)


;whenever you want to get rid of the references to previous errors:
[1] USER(40): :reset



SER(47): (defun average (x y) (/ (+ x y ) 2))
AVERAGE
USER(48): (average 4 8)
6
USER(49): (average (* 3 4) (/ 24 6))
8
USER(50): (print "free variables in functions")

"free variables in functions"
"free variables in functions"
USER(51): (defun whatever (x y)
             (setq sum (+ x y))
               (/ sum 2))
WHATEVER
USER(52): (whatever 29 13)
21
USER(53): sum
42
USER(54): (print "why is this bad?")
"why is this bad?"
"why is this bad?"                


;BECAUSE it creates global reference
;better to use let to create LOCAL bindings

USER(57): 
(defun whatever (x y)
  (let
      (  (sum2 ( + x y ))  )
	 (/ sum2 2)
	)
)
WHATEVER
USER(58): (whatever 29 13)
21
USER(59): sum2
Error: Attempt to take the value of the unbound variable `SUM2'.
[condition type: UNBOUND-VARIABLE]
Restart actions (select using :continue):
0: Try evaluating SUM2 again.
1: Set the symbol-value of SUM2 and use its value.
2: Use a value without setting SUM2.   




[1] USER(60): (print "now for predicates")

"now for predicates"
"now for predicates"


;T is the return value when predicate is satisfied
;nil is the return value when it is not

[1] USER(61): (atom 'a)
T
[1] USER(62): (atom '(1 2))
NIL
[1] USER(63): (listp 'a)
NIL
[1] USER(64): (listp '(1 2))
T
[1] USER(65): (listp nil)
T
[1] USER(66): (null '(1))
NIL
[1] USER(67): (null nil)
T
[1] USER(68): (null '())
T
[1] USER(69): (equal 'a 'b)
NIL
[1] USER(70): (equal 'a 'a)
T
[1] USER(71): (setq x 'a)
A
[1] USER(72): (setq y 'b)
B
[1] USER(73): (equal x y)
NIL
[1] USER(74): (setq y 'a)
A
[1] USER(75): (equal x y)
T  
[1] USER(77): :reset


USER(78): (setq x '(1 2 3))
(1 2 3)
USER(79): (setq y '(a (1 2 3) b))
(A (1 2 3) B)
USER(80): (equal x (cadr y))
T
USER(81): (eq x (cadr y))
NIL    
USER(82): (member 'b '(a b c))
(B C)
USER(83): (member x y)
NIL                                     

;member uses a test called eq which tests for "pointer equality", i.e. these two
;things are actually the same piece of memory
;whereas equal tests for structural equality.  (1 2 3) equals (1 2 3) even if
;they are different memory structures because they have identical structure

USER(85): (member x y :test #'equal)
((1 2 3) B)  


;for example, member with the different tests are used here in this cond example
;cond is like a switch statement

USER(89): 
(let (  (x '(1 2 3) )  (y '(a b c)) )
  (cond
   (   (member x '((-2 -1 0) (1 2 3) (4 5 6)) :test #'eq) 
	          (print "x was a match") (print "ta-dah") )
   (   (member y '((u v w) (x y z) (a b c))   :test #'eq) 
	          (print "y was a match") (print "but we never know it") )
   ( t  (print "default action") ) ) )

"default action"
"default action"

USER(90): 
(let (  (x '(1 2 3) )  (y '(a b c)) )
  (cond
    (   (member x '((-2 -1 0) (1 2 3) (4 5 6)) :test #'equal) 
	          (print "x was a match") (print "ta-dah") )
    (   (member y '((u v w) (x y z) (a b c))   :test #'equal) 
	          (print "y was a match") (print "but we never know it") )
    ( t  (print "default action") ) ) )
"x was a match"
"ta-dah"
"ta-dah"          

;question: why does the last print show up twice?



;recursion

USER(91): 
(defun factorial (n)
  (cond
    ( (= 0 n) 1)
	  ( t (* n (factorial (- n 1))))))
FACTORIAL
USER(92): (factorial 4)
24                  


;what's wrong with this version?!!
USER(94): 
(defun myreverse (ls)
  (cond
    ( (null ls) ls)
	  (t (append (myreverse (cdr ls)) (car ls)))))
USER(95):(myreverse '(a b c))
(C B . A)     

; aha, one of those weird dotted pairs
; why, because the (car ls) is not a list and was given to append
; which requires lists

;how do we fix?
; there are better ways, but here is one

USER(96):
  (defun myreverse (ls)
     (cond
		   ( (null ls) ls)
			 (t (append (myreverse (cdr ls)) (list (car ls))))))   
USER(97): (myreverse '(a b c))
(C B A) 

;you may find the following function useful!!!!

(load "<filename>")

;<filename> should be a pathname to the file of LISP code you wish to load
;if you are running cl in the same directory as the code, just the name is fine


;also

(trace <function_name>)

;will cause the interpreter to show you the precise sequence of calls
;made during an evaluation to the function specified by <function_name> which
;should not be quoted!!  For example:

USER(1): (trace +)
(+)
USER(2): (+ 2 (+ 3 (+ 4 5)))
0: (+ 4 5)
0: returned 9
0: (+ 3 9)
0: returned 12
0: (+ 2 12)
0: returned 14
14              


USER(150): :exit
Exiting Lisp.



[ Back to CS451: The LISP Segment ]