cond
cond Macro
Syntax:
cond {↓clause}* → {result}*
clause::=(test-form {form}*)
Arguments and Values:
test-form—a form.
forms—an implicit progn.
results—the values of the forms in the first clause whose test-form yields true, or the primary value of the test-form if there are no forms in that clause, or else nil if no test-form yields true.
Description:
cond allows the execution of forms to be dependent on test-form.
Test-forms are evaluated one at a time in the order in which they are given in the argument list until a test-form is found that evaluates to true.
If there are no forms in that clause, the primary value of the test-form is returned by the cond form. Otherwise, the forms associated with this test-form are evaluated in order, left to right, as an implicit progn, and the values returned by the last form are returned by the cond form.
Once one test-form has yielded true, no additional test-forms are evaluated. If no test-form yields true, nil is returned.
Examples:
(defvar a) → a
(defun select-options ()
(cond ((= a 1) (setf a 2))
((= a 2) (setf a 3))
((and (= a 3) (floor a 2)))
(t (floor a 3)))) → SELECT-OPTIONS
(setf a 1) → 1
(select-options) → 2
a → 2
(select-options) → 3
a → 3
(select-options) → 1
(setf a 5) → 5
(select-options) → 1, 2
See Also:
if, case.
We fixed the examples so that it uses defvar to initialize the variable and to use setf rather than setq for assignment.
Expanded Reference: cond
Basic multi-way conditional
cond evaluates test forms in order. When a test returns true, the corresponding body forms are evaluated and their result is returned. No further clauses are tested.
(defun describe-number (n)
(cond
((< n 0) "negative")
((= n 0) "zero")
(t "positive")))
(describe-number -5)
=> "negative"
(describe-number 0)
=> "zero"
(describe-number 42)
=> "positive"
The t clause as a default
A clause with t as the test form always matches. It is conventionally placed last to act as a default case.
(defun classify-char (ch)
(cond
((alpha-char-p ch) :letter)
((digit-char-p ch) :digit)
(t :other)))
(classify-char #\a)
=> :LETTER
(classify-char #\5)
=> :DIGIT
(classify-char #\!)
=> :OTHER
Returning NIL when no clause matches
If no test form evaluates to true and there is no default clause, cond returns NIL.
(cond
((> 1 2) "impossible")
((< 5 3) "also impossible"))
=> NIL
Clauses with no body forms
When a clause has no body forms, the primary value of the test form itself is returned.
(cond
(nil)
(42)
(t "not reached"))
=> 42
Multiple body forms in a clause
Each clause supports multiple body forms (an implicit progn). All forms are evaluated and the last value is returned.
(let ((x 10))
(cond
((> x 100)
(format t "Very large~%")
:very-large)
((> x 5)
(format t "Moderate~%")
:moderate)
(t
(format t "Small~%")
:small)))
.. Moderate
..
=> :MODERATE
Using cond to implement FizzBuzz
A practical example showing cond with compound test expressions.
(defun fizzbuzz (n)
(cond
((zerop (mod n 15)) "FizzBuzz")
((zerop (mod n 3)) "Fizz")
((zerop (mod n 5)) "Buzz")
(t n)))
(fizzbuzz 3)
=> "Fizz"
(fizzbuzz 5)
=> "Buzz"
(fizzbuzz 15)
=> "FizzBuzz"
(fizzbuzz 7)
=> 7