LISP uses the self-evaluating symbol nil
to mean false. Anything other
than nil
means true. Unless we have a reason not to, we usually use the
self-evaluating symbol t
to stand for true.
LISP provides a standard set of logical functions, for example
and
, or
,
and not
. The and
and or
connectives are
short-circuiting: and will not
evaluate any arguments to the right of the first one which evaluates to
nil
, while or
will not evaluate any arguments to the right
of the first
one which evaluates to t
(with t
we mean here ``non-nil
'').
LISP also provides several special forms for conditional execution. The
simplest of these is if
. The first argument of if
determines whether
the second or third argument will be executed:
> (if t 5 6)
5
> (if nil 5 6)
6
> (if 4 5 6)
5
If you need to put more than one statement in the then or else clause
of an if statement, you can use the progn
special
form. Progn
executes
each statement in its body, then returns the value of the final one.
> (setq a 7)
7
> (setq b 0)
0
> (setq c 5)
5
> (if (> a 5)
(progn
(setq a (+ b 7))
(setq b (+ c 8)))
(setq b 4))
13
An if
statement which lacks either a then or an else clause can be
written using the when
or unless
special form:
> (when t 3)
3
> (when nil 3)
NIL
> (unless t 3)
NIL
> (unless nil 3)
3
When
and unless
, unlike if
, allow any number of
statements in their
bodies. (Eg, (when x a b c)
is equivalent to
(if x (progn a b c))
.)
> (when t
(setq a 5)
(+ a 6))
11
More complicated conditionals can be defined using the cond
special
form, which is equivalent to an if ... else if ... fi construction.
A cond
consists of the symbol cond
followed by a number of cond
clauses, each of which is a list. The first element of a cond clause is
the condition; the remaining elements (if any) are the action. The cond
form finds the first clause whose condition evaluates to true (ie,
doesn't evaluate to nil); it then executes the corresponding action and
returns the resulting value. None of the remaining conditions are
evaluated; nor are any actions except the one corresponding to the
selected condition. For example:
> (setq a 3)
3
> (cond
((evenp a) a) ;if a is even return a
((> a 7) (/ a 2)) ;else if a is bigger than 7 return a/2
((< a 5) (- a 1)) ;else if a is smaller than 5 return a-1
(t 17)) ;else return 17
2
If the action in the selected cond clause is missing, cond
returns what
the condition evaluated to:
> (cond ((+ 3 4)))
7
Here's a clever little recursive function which uses cond
. You might be
interested in trying to prove that it terminates for all integers x
at
least 1. (If you succeed, please publish the result.)
> (defun hotpo (x steps) ;hotpo stands for Half Or Triple Plus One
(cond
((= x 1) steps)
((oddp x) (hotpo (+ 1 (* x 3)) (+ 1 steps)))
(t (hotpo (/ x 2) (+ 1 steps)))))
A
> (hotpo 7 0)
16
The LISP case statement is like a C switch statement:
> (setq x 'b)
B
> (case x
(a 5)
((d e) 7)
((b f) 3)
(otherwise 9))
3
The otherwise clause at the end means that if x
is not a
,
b
, d
, e
, or f
, the case statement will return 9.