Lisp practice/warmup exercise

Since we're losing on lab/lecture at the start of the term (with Dave off sick) this is meant as a practical warmup to get used to lisp nuts and bolts.

  1. Login to your account on one of the cubs/pups/tux, create a directory for this practice exercise, and use your favorite text editor to create two files: practice.cl and utils.cl.

  2. practice.cl will be the executable script and will load/call functions from utils.cl, so put the following in practice.cl:
    #! /usr/bin/sbcl --script
    (load "utils.cl")
    

  3. From the command line, make practice.cl executable, e.g.
    chmod u+x practice.cl

  4. In utils.cl define two functions, smallest and product, where each takes three parameters, e.g. x,y,z. For now just give them empty bodies and a description string (smallest is shown below).

    Ultimately, smallest will return the smallest number out of its three parameters, product will return the product of its three numeric parameters, smallest returns nil if all the parameters are invalid, product returns 1 if all the parameters are invalid.
    (defun smallest (x y z)
       "returns the smallest number out of x,y,z: nil if none of them are numbers"
       )
    

  5. In practice.cl use defvar to create variables small and prod, initializing each to zero, e.g.
    (defvar small 0)

    Then use setf to set small and prod to the results of calls to smallest and product, e.g.
    (setf small (smallest 10 5.1 123))

    Then use format to print out the two values, e.g.
    (format t "Small is ~A~%" small)

  6. From the command line run ./practice.cl to see if it loads/compiles/runs cleanly. Both should just come out nil since neither function actually has any content yet.

  7. Try a simple multiplication as the body of product, e.g. (* x y z), which would go after the description string and before the final )

    Try running ./practice.cl again to see if it computes and returns the correct result.

  8. Try nested if's to return the correct result for smallest, e.g.
    (defun smallest (x y z)
       "returns the smallest number out of x,y,z: nil if none of them are numbers"
       (if (and (<= x y) (<= x z)) x  ; if x is smallest return x
           (if (<= y z) y                 ; else if y <= z return y
                        z)))              ; else return z
    

    Try running ./practice.cl again and see if you have the syntax correct, and possibly try additional valid calls from practice to see if it works correctly when the first/last are the smallest.

  9. Now revise practice.cl so it gets the values for x,y,z from the reader, and uses those in the calls to product and sum, e.g.
    (format t "Enter three values for testing~%")
    (defvar x (read))
    (defvar y (read))
    (defvar z (read))
    (setf prod (smallest x y z))
    

  10. In product, try replacing each of x, y, z in the computation with a statement that checks the type of x (or y or z) and returns 1 if it's not a number.
    For example: (if (numberp x) x 1) returns x if x is a number, 1 otherswise, so we can use this if statement in place of x in our earlier computation in product:
    (defun product (x y z)
       "blahblahblah"
       (* (if (numberp x) x 1) y z))
    
    Then do similarly for the y and z arguments.

    Try ./practice.cl again with the valid value, just to make sure we haven't broken anything, then try with some non-numeric combinations to test.

  11. Now try revising smallest to check types as well: you might find it easiest to switch smallest to a cond for this, e.g. one kinda brute force approach is:
    (defun smallest (x y z)
       "blahblahblah"
       (cond
          ((not (or (numberp x) (numberp y) (numberp z)))    nil) ; none of them were numbers
          ((not (or (numberp x) (numberp y)))                  z) ; z must be the only number
          ((not (or (numberp x) (numberp z)))                  y) ; y must be the only number
          ((not (or (numberp y) (numberp z)))                  x) ; x must be the only number
          ((and (not (numberp x)) (<= y z))                    y) ; y and z are numbers, y is smaller
          ... etc etc ...
       ))