Music 220b: Winter 2001

Fernando Lopez-Lezcano, instructor

Christopher Burns, teaching assistant

Tamara Smyth, teaching assistant

Week 2: logic - (if) and (cond)

We often want our lisp programs to make decisions. For instance, we might generate **(with-sound)** calls using a list of frequencies, and use different instruments depending upon the frequency. Or, we might analyze a soundfile, and take different actions depending upon the maximum amplitudes in a particular region.

In order to do these kinds of things, we need logical tests. Lisp provides two commands for this purpose: (if) and (cond).

**(if)**The body of an if statement has three sections, quickly summarized as "if," "then," and "else." In full syntax:

(if (

*test-clause*) (*then-clause*) (*else-clause*))For instance, "if the current frequency is greater than 440, generate a sound from fm-violin; else generate a sound from grani." Try -

CM(1): :cl /zap/v CM(2): :cl /zap/grani CM(3): (setf frequency 450) CM(4): (with-sound (:statistics t :srate 44100) (if (> frequency 440) (fm-violin 0 1 frequency 0.3) (grani 0 1 0.3 "/zap/cencerros-1.snd")))

For a more simple example, "if the frequency list has more than five elements, print a warning, otherwise return t [true]":

CM(8): (setf frequency-list (list 440 220 660 110 880 330)) CM(9): (if (> (length frequency-list) 5) (format t "frequency list is too long....") t) frequency list is too long.... NIL CM(13): (setf frequency-list (list 440 220)) CM(14): (if (> (length frequency-list) 5) (format t "frequency list is too long....") t) T

This kind of test is often usefully expressed as a function:

(defun check-frequency-list-length (frequency-list) (if (> (length frequency-list) 5) (format t "frequency list is too long....") t))

**(cond)**Cond is a more generic logic test than if; it allows you to specify many different conditions, instead of just one. This first example squares positive numbers, and returns the negative square of a negative number. In any other case it returns zero. ("t" automatically evaluates to true -- the equivalent of our else condition in the (if) statement).

(defun cond-example (number) (cond ((> number 0) (* number number)) ((< number 0) (- (* number number))) (t 0))) CM(18): (cond-example 3) 9 CM(19): (cond-example -3) -9 CM(20): (cond-example 0) 0

In case the example doesn't make it clear, the cond syntax works like this:

(cond ((

*test-1*) (*do-this-if-test-1-is-true*)) ((*test-2*) (*do-this-if-test-2-is-true*)) ...arbitrary number of tests... ((*test-n*) (*do-this-if-test-n-is-true*)) (t (*do-this-if-all-tests-fail*)))Note that the tests are evaluated sequentially -- the interpreter tries test-2 only if test-1 fails. This means that the order of the tests are important.

So far we've only seen the simplest applications of if and cond; but they are the building blocks of far more complicated programs. Let your imagination run wild....