Allegheny College
Department of Computer Science
CS220 Programming Languages
Lab 7, March 12, 2007

CLISP


Table of Contents

  1. Getting Started...
  2. Using the CLISP Command Interpreter
  3. Dribble
  4. If-Statements
  5. List Processing & Symbolic Manipulation
  6. Sample Problems
  7. Lisp Functions
  8. Online Resources
  9. Lab Assignment

Getting Started

CLISP

To invoke the clisp command interpreter:    $clisp   

To compile a lisp source code file into an executable:    $clisp -c lisp-file.lisp -o out-put-file

To view the clisp manual page:    $man clisp

Back to Top

Using the CLISP Command Interpreter

1.    [1]>    10
2.    [2]>    -3
3.    [3]>    "hello"
4.    [4]>    t
5.    [5]>    nil
6.    [6]>    ()
7.    [7]>    (not t)
8.    [8]>    (not nil)
9.    [9]>    (and t t)
10.[10]>    (and nil t)
11.[11]>    (or t nil)
12.[12]>    (or () ())
13.[13]>    (+ 10 -3)
14.[14]>    (- 10 -3)
15.[15]>    (+ 2 4 5 9 11)
16.[16]>    (* 1.5 -6.5)
17.[17]>    (/ 100 15)
18.[18]>    (/ 100.0 15)
19.[19]>    (! 4)
20.[20]>    (! 50)
21.[21]>    (> 5 6)
22.[21]>    (> 6 5)
23.[22]>    (<= 10 10)
24.[32]>    (/ 45 3)
25.[23]>    (= 15 45/3) 
26.[24]>    (- (+ 12 3) (* 4 9))
27.[25]>    (/ (- 10 7) (sqrt 64))))))))))))))))))))
28.[25]>    (/ (- 10 7) (sqrt 64))
29.[26]>    (expt 2 4)
30.[27]>    (expt 64 .5)
 
31.[28]>    ; area of a circle with radius 5
32.[29]>    (* pi 5 5)
33.[30]>    ; convert 212 degrees Fahrenheit into Celsius
34.[31]>    (* 5/9 (- 212 32))
35.[32]>    ; convert 20 degrees Celsius into Fahrenheit
36.[33]>    (+ (* 9/5 21) 32)
37.[34]>    ; same, floating point
38.[35]>    (+ (* 9/5 21) 32.0)))))))
 
39.[36]>    ; define coefficients of the 2nd-degree polynomial 3x*x - 2*x - 1
40.[37]>    (setf a 3)
41.[38]>    (setf b -2)
42.[39]>    (setf c -1)
43.[40]>    a
44.[41]>    b
45.[42]>    c
46.[43]>    (list a b c)
47a.[44]>    (a b c)
47b.[44]>    '(abc)
47c.[44]>    'a
 
48.[46]>    ; quadratic formula (-b + sqrt(b*b - 4*a*c))/(2*a)
49.[47]>    (/ (+ (- b) (sqrt (- (expt b 2) (* 4 a c)))) (* 2 a))
50.[48]>    ; quadratic formula (-b - sqrt(b*b - 4*a*c))/(2*a)
51.[49]>    (/ (- (- b) (sqrt (- (expt b 2) (* 4 a c)))) (* 2 a))
 
52.[50]>    (defun quad1 (a b c)
53.[51]>      "finds first solution to quadratic equation ax*x + b*x + c = 0"
54.[52]>       (/ (+ (- b) (sqrt (- (expt b 2) (* 4 a c)))) (* 2 a))
55.[53]>    )
56.[54]>    (quad1 3 -2 -1)
57.[55]>    (quad1 1 2 1)
58.[56]>    (quad1 1 1 1)
 
59.[57]>    (defun quad2 (a b c)
60.[58]>      "finds second solution to quadratic equation ax*x + b*x + c = 0"
61.[59]>       (/ (- (- b) (sqrt (- (expt b 2) (* 4 a c)))) (* 2 a))
62.[60]>    )
63.[61]>    (quad2 3 -2 -1)
 
64.[62]>    (defun solve-quad (a b c) 
65.[63]>      "finds both solutions to ax*x + b*x + c = 0"
66.[64]>       (list (quad1 a b c) (quad2 a b c))
67.[65]>    )
68.[66]>    (solve-quad 3 -2 -1)
69.[67]>    (solve-quad 1 1 1)
70.[68]>    (solve-quad  28.12 18.4 -12.4)
 
Back to Top

Dribble

To save or record your interactions with the CLISP command interpreter, use the dribble command:

[1]> (dribble "name-of-output-file")

[2]> ....

[nn]>(dribble)

[nn+1]>(bye)

Back to Top

If-Statements  

[1]> (defun ticket-price (age)
      "Given the age of the purchaser, returns cost of a movie ticket:
       $6.00 for adults, $4.50 for children under 12."
        (if (>= age 12) 6 4.5)
    )
[2]> (ticket-price 14)
   6
[3]> (ticket-price 9)
    4.5
    (ticket-price 14)
NESTED IF STATEMENTS
 [1]> (defun temperature (degrees)
         "classify temperature as below freezing, freezing, or above freezing"
         (if (< degrees 32)
             "below freezing"
             (if (= degrees 32)
                 "freezing"
                 "above freezing"
             )
         )
    )))))))
 [2]> (temperature 45)
    "above freezing"
 [3]> (temperature 0)
    "below freezing"
 [4]> (temperature 32)
    "freezing"
Back to Top

List Processing & Symbolic Manipulation


[2]> (setf friends '(dick jane sally))
(DICK JANE SALLY)
[3]> friends
(DICK JANE SALLY)
[4]> (setf enemies '(troll grinch ghost))
(TROLL GRINCH GHOST)
[5]> enemies
(TROLL GRINCH GHOST)
[10]> (setf enemies (remove 'ghost enemies)))
(TROLL GRINCH)
[11]> enemies
(TROLL GRINCH)
[12]> (setf friends (cons 'ghost friends))
(GHOST DICK JANE SALLY)
[13]> friends
(GHOST DICK JANE SALLY)
[14]> (defun newfriend (name)
(setf enemies (remove name enemies))
(setf friends (cons name friends)))
NEWFRIEND
[17]> (newfriend 'troll)
(TROLL GHOST DICK JANE SALLY)
[18]> friends
(TROLL GHOST DICK JANE SALLY)
[21]> enemies
(GRINCH)
[22]> (first '(lots of irritating parenthesis))
LOTS
[23]> (rest '(lots of irritating parenthesis))
(OF IRRITATING PARENTHESIS)
[24]> (first (rest (a b c)))

*** - EVAL: the function A is undefined
1. Break [25]>
[26]> (first (rest '(a b c)))
[27]> (first '(rest (a b c)))
REST
[28]> (cadr '(a b c))
B
[29]> (car (cdr '(a b c)))
B
[30]> (first (rest '(a b c)))
B
[31]> t
T
[32]> nil
NIL
[33]> (append '(a b) '(c))
(A B C)
[34]> (append '(a b C) '())
(A B C)
[35]> (list '(a b c) '())
((A B C) NIL)
[36]> (cons '(a b c) '())
((A B C))
[37]> (defun power (m n)
(if (zerop n)
1
(* m
(power m (- n 1)
))))
POWER
[38]> (power 2 2)
4
[39]> (power 2 1)
2
[40]> (power 2 0)
1

 

Back to Top

Sample Problems

#1.    Create a function that solves quadratic equations (see Using the CLISP Command Interpreter), and displays the answers in the following form:

[44]> (solve-quad 1 1 1)
    ("two complex solutions" #C(-1/2 0.8660254) #C(-1/2 -0.8660254))
[45]> (solve-quad 1 2 1)
    ("one real solution" -1)
[46]> (solve-quad 3 -2 -1)
    ("two real solutions" 1 -1/3)

Solution:

 [1]> (defun quad1 (a b sol)

(/ (+ (- b) (sqrt sol)) (* 2 a)))
 QUAD1
 [2]> (defun quad2 (a b sol)

(/ (- (- b) (sqrt sol)) (* 2 a)))
 QUAD2
 [3]> (defun solve-quad (a b c)

(setf sol (- (expt b 2) (* 4 a c)))

(if (< sol 0)
(list "two complex solutions"

(quad1 a b sol) (quad2 a b sol))

(if (> sol 0)

(list "two real solutions" (quad1 a b sol) (quad2 a b sol)) (list "one real solution" (quad1 a b sol)))))

SOLVE-QUAD
[4]> (solve-quad 1 2 1)
 ("one real solution" -1)
[5]> (solve-quad 1 1 1)
 ("two complex solutions" #C(-1/2 0.8660254) #C(-1/2 -0.8660254))
[6]> (solve-quad 5 -4 -2)
 ("two real solutions" 1.1483314 -0.3483315)


#2 Create a function that creates a list consisting of all the numbers from 1 through n, where n is any positive integer.

Hint:  The append function takes two or more lists and merges them into a single list.  Compare the ouput of the following two statements:

[1]> (list 1 2 3) (1 2 3)

[2]> (append ‘(1) ‘(2) ‘(3)) (123)

 

Solution:

[3]>(defun number-list (n)

           “create a list containing the integers from 1 through n”

           (if (<= n 0)

                 nil ; empty list if n is 0 or less

                 (append (number-list (- n 1)) (list n))

     )))))))

NUMBER-LIST

[4]>(number-list 3)

(1 2 3)

[5]>(number-list 0)

NIL

[6]>(number-list 10)

(1 2 3 4 5 6 7 8 9 10)

 

#3  Create a function named square-list that accepts a positive integer n. It should return a list of the frist n squares. 

Sample Output:

[8]> (square-list 2)
    (1 4)
[9]> (square-list 1)
    (1)
[10]> (square-list 2)
    (1 4)
[11]> (square-list 10)
    (1 4 9 16 25 36 49 64 81 100)
[12]> (square-list -2)
    NIL
Solution

(defun square-list (n)

  "Returns a list of the first n squares"

  (if (<= n 0) ;then

      nil ;else

      (append (square-list (- n 1)) (list (* n n)))

  ))

 

 

Back to Top

Online Resources

Nice list of online resources
Common Lisp HyperSpec Online version of the Common Lisp standard
Pascal Costanza's Highly Opinionated Guide to Lisp
Common Lisp Language Overview
"Common Lisp: The Language (2nd ed)" by Guy Steele
Object Oriented and Procedural Lisp
"Lisp as an alternative to Java" (PDF file) From Intelligence, Volume 11, Issue 4 (December 2000), 21-24.
Complete text of Touretzky's book on Common Lisp
The Common Lisp Cookbook (lots of Lisp links at bottom)
Complete text of Graham's "On Lisp"
Common Lisp pitfalls (more advanced)

Back to Top

Lisp Functions

Remember that in general, functions evaluate their arguments, but there are some important exceptions to this. All exceptions are noted.

   (+ x y), (- x y), (* x y), (/ x y)
       --- Arithmetic functions of numbers.  You can do things like (+ x y z w).
       
   (random x)
      --- If x is a positive integer, returns a random integer R satisfying
      0 <= R < x.  If x is a positive real number, returns a random real
      number satisfying the same condition.  (Note that (random 1) is always
      equal to 0, while (random 1.0) is a real number between 0.0 and 1.0.)

   (first lst), (second lst), ... (tenth lst)
       --- Extract one of the elements of a list

   (rest lst)
      --- Returns the list obtained by removing the fist element in lst.

   (car lst), (cdr lst)
      --- Traditional names for (first lst) and (rest lst)

   (cons expr lst)
      --- Returns the list obtained by adding (the value of) expr onto
      the front of lst.  Note that (car (cons expr lst)) is the same
      as expr, and (cdr (cons expr lst)) is the same as lst.

   (list expr1 expr2 ...)
      --- Returns the list whose elements are (the values of) expr1, expr2, ...

   (append lst1 lst2 ...)
      --- Returns the list obtained by stringing together the elements of
      lst1, lst2, ... into a single list.

   (quote foo)
      --- Returns its parameter without evaluating it.  So, for example, the
      value of (quote a) is the symbol a and the value of (quote (a b c))
      is the list (a b c).  (quote foo) is almost always abbreviated using
      the special notation 'foo.  For example, 'a or '(a b c).

   (= x y), (< x y), (> x y), (<= x y), (>= x y), (/= x y)
      --- Boolean functions for testing numbers.  ("/=" is "not equal")

   (equal a b), (eq a b)
      --- Tests whether a and b are equal.  These have the same effect for
      numbers, symbols, and strings.  For lists, equal tests whether
      the lists have the same members, while eq tests whether they
      actually occupy the same memory location; it is like pointer equality.
      Thus, (eq '(a b) '(a b)) is false, but after (setq lst '(a b)), 
      (eq lst lst) would be true.

   (null x)
      --- Tests whether x is NIL.

   (atom x), (listp x), (stringp x), (numberp x), (symbolp x), (floatp x), (integerp x)
      --- Test whether x is of the specified type.

   (oddp x), (evenp x), (zerop x)
      --- Test properties of numbers.
      
   (not p), (and p q ...), (or p q ...)
      --- The usual boolean functions.  Note that and and or can take
      multiple arguments.  Also, AND and OR are often used as control
      structures:  AND evaluates its arguments until one comes out false, OR
      evaluates its arguments until one comes out true (i.e. non-NIL); if OR
      finds a non-NIL value, that value becomes the value of the OR.
      
   (print x), (prin1 x), (terpri), (princ x)
      ---Output functions.  (print x) outputs the value of x, followed by a
      carriage return.  (prin1 x) outputs the value of x without a carriage
      return.  (terpri) outputs a carriage return.  Note that the value 
      returned by prin1 or print is the same as the value that was printed.
      (princ x) is like (print x), except that, for example, quotes around
      strings are NOT included in the output.
      
   (read)
      --- An input function.  Lets the user type in a Lisp expression, and
      returns that expression as its value.

   (setq var expr) 
      --- Assigns the value of expr to var.
      var is not evaluated and must be a symbol.  Note that the value
      that is returned by setq is the same as the value assigned to the variable.

   (defun func (arg1 arg2 ...) expr1 expr2 ...)
      --- Defines a function named func.  arg1, arg2, ... are dummy parameters for
      the function.  func, arg1, arg2, ... are not evaluated and must be symbols.
      When the function is called, expr1, expr2, ... are evaluated in order.
      The value returned by the function is the value of the last expression,
      unless a (return) causes the function to return early.

   (return expr)
      --- Breaks out of a loop, function, progn, etc.  The value of expr 
      becomes the value of the loop or function.  expr is optional; if it 
      is omitted, then the value is NIL.

   (if test expr1 expr2)
      --- Evaluates test.  If it is true, expr1 is evaluated and its
      value becomes the value of the if expression.  In this case, expr2
      is never evaluated.  If test is false, then expr2 is evaluated,
      its value becomes the value of the if expression, and expr1 is 
      never evaluated.  expr2 is optional.  If it is missing and if
      test is false, then the value of the if is NIL.

   (loop expr1 expr2 ...)
      --- Repeatedly evaluates expr1, expr2, ... until a (return) or (return expr)
      is executed.  The value of the loop is the value returned by the (return).

   (progn expr1 expr2 ...)
      --- Executes expr1, expr2, once, in order.  (This can be useful, for example
      in an if, if you want to evaluate more than one one expression.)

   (let ( (var1 val1) (var2 val2) ... )  expr1 expr2 ...)
      --- var1, var2, ... become local variables that are assigned the
      specified values as their initial values.  var1, var2, ... must be
      symbols,  and they are not evaluated.  expr1, expr2, ... are
      then evaluated.  The value of the let expression is the value of the
      last expr.

   (dolist (var lst) expr1 expr2 ...)
      --- var (which is not evaluated and must be a symbol) takes on the
      value of each element of the list lst in turn.  For each of these
      values, the expressions expr1, expr2, are evaluated.  For example,  
      (dolist (x '(a b c)) (print x)) will print a, then b, then c.
      
   (cond 
         (test1 expr expr ...)
         (test2 expr expr ...)
         .
         .
         .
         (testn expr expr ...)
       )
      --- This is the traditional (if... else if... else if...) in Lisp.
      test1 is evaluated.  If it is true, the expressions following
      test1 are executed.  The cond terminates, and its value is
      the value of the last expression that was executed.  If test1 is
      false, then test2 is checked in the same way.  And so on.  If 
      all the tests are false, then the value of the cond is NIL.
      Note that the last test is often the atom T, whose value is true, 
      guaranteeing that the last set of expressions will be executed if none 
      of the previous ones are.
Back to Top

Lab Assignment

Exercise I

Use the laboratory to work through the CLISP examples found in the above sections:

  1. Using the CLISP Command Interpreter
  2. Dribble
  3. If-Statements
  4. List Processing & Symbolic Manipulation
  5. Sample Problems

Use the "dribble" command to record your session with the interpreter as you work through the examples in Using the CLISP Command Interpreter.

Exercise II

Design and Implement CLISP solutions to the following problems using the CLISP Interpreter.

  1. Write a function (cube x) that returns the cube (x*x*x) of its argument.  (Assume the parameter is a number.)
  2. Write a function that takes 2 integers as input and returns a random number between the two.
  3. Write a function (fact n), that calculates the factorial of a number n.
  4. Write a recursive solution to the Fibonacci Problem.
  5. Write a recursive function that returns a list of the first and last elements of a list (w/out using the last function).
  6. Write a recursive function to count the items in a list.  For example, (count '(a (b c) d) would be 3.  (Note that the an element that is a list is still a single element.)

Deliverables

On Monday, March 26, 2007 hand-in copies of your recorded "dribble" session for Exercise I, as well as the solutions to the 5 problems in Exercise II.

Back to Top

Matthew T. Engel
Systems Administrator
Allegheny College Department of Computer Science
Meadville, PA 16335
Copyright © 2001  [A.C.D.O.C.S.]. All rights reserved.
Revised: 04/06/05, 4/12/07 (A. Thall)