emacs.d/clones/lisp/www.cs.cmu.edu/Groups/AI/html/cltl/clm/node84.html

279 lines
14 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3O//DTD W3 HTML 2.0//EN">
<!Converted with LaTeX2HTML 0.6.5 (Tue Nov 15 1994) by Nikos Drakos (nikos@cbl.leeds.ac.uk), CBLU, University of Leeds >
<HEAD>
<TITLE>7.6. Conditionals</TITLE>
</HEAD>
<BODY>
<meta name="description" value=" Conditionals">
<meta name="keywords" value="clm">
<meta name="resource-type" value="document">
<meta name="distribution" value="global">
<P>
<b>Common Lisp the Language, 2nd Edition</b>
<BR> <HR><A NAME=tex2html2572 HREF="node85.html"><IMG ALIGN=BOTTOM ALT="next" SRC="icons/next_motif.gif"></A> <A NAME=tex2html2570 HREF="node76.html"><IMG ALIGN=BOTTOM ALT="up" SRC="icons/up_motif.gif"></A> <A NAME=tex2html2564 HREF="node83.html"><IMG ALIGN=BOTTOM ALT="previous" SRC="icons/previous_motif.gif"></A> <A NAME=tex2html2574 HREF="node1.html"><IMG ALIGN=BOTTOM ALT="contents" SRC="icons/contents_motif.gif"></A> <A NAME=tex2html2575 HREF="index.html"><IMG ALIGN=BOTTOM ALT="index" SRC="icons/index_motif.gif"></A> <BR>
<B> Next:</B> <A NAME=tex2html2573 HREF="node85.html"> Blocks and Exits</A>
<B>Up:</B> <A NAME=tex2html2571 HREF="node76.html"> Control Structure</A>
<B> Previous:</B> <A NAME=tex2html2565 HREF="node83.html"> Establishing New Variable </A>
<HR> <P>
<H1><A NAME=SECTION001160000000000000000>7.6. Conditionals</A></H1>
<P>
The traditional conditional construct in Lisp is <tt>cond</tt>.
However, <tt>if</tt> is much simpler and is directly comparable
to conditional constructs in other programming languages,
so it is considered to be primitive in Common Lisp and is described first.
Common Lisp also provides the dispatching constructs <tt>case</tt> and <tt>typecase</tt>,
which are often more convenient than <tt>cond</tt>.
<P>
<BR><b>[Special Form]</b><BR>
<tt>if <i>test</i> <i>then</i> [<i>else</i>]</tt>
<P>The <tt>if</tt> special form corresponds to the <b>if</b>-<b>then</b>-<b>else</b> construct
found in most algebraic programming languages.
First the form <i>test</i> is evaluated. If the result is not <tt>nil</tt>,
then the form <i>then</i> is selected; otherwise the form <i>else</i> is selected.
Whichever form is selected is then evaluated, and <tt>if</tt> returns
whatever is returned by evaluation of the selected form.
<P><pre>
(if <i>test</i> <i>then</i> <i>else</i>) == (cond (<i>test</i> <i>then</i>) (<tt>t</tt> <i>else</i>))
</pre><P>
but <tt>if</tt> is considered more readable in some situations.
<P>
The <i>else</i> form may be omitted, in which case if the value of <i>test</i>
is <tt>nil</tt> then nothing is done and the value of the <tt>if</tt> form is <tt>nil</tt>.
If the value of
the <tt>if</tt> form is important in this situation, then the <tt>and</tt>
construct may be stylistically preferable,
depending on the context.
If the value is not important, but only the effect, then the <tt>when</tt>
construct may be stylistically preferable.
<P>
<BR><b>[Macro]</b><BR>
<tt>when <i>test</i> {<i>form</i>}*</tt><P><tt>(when <i>test</i> <i>form1</i> <i>form2</i> ... )</tt>
first evaluates <i>test</i>. If the result is <tt>nil</tt>,
then no <i>form</i> is evaluated, and <tt>nil</tt> is returned.
Otherwise the <i>form</i>s constitute an implicit <tt>progn</tt>
and are evaluated sequentially from left to right,
and the value of the last one is returned.
<P><pre>
(when <i>p</i> <i>a</i> <i>b</i> <i>c</i>) == (and <i>p</i> (progn <i>a</i> <i>b</i> <i>c</i>))
(when <i>p</i> <i>a</i> <i>b</i> <i>c</i>) == (cond (<i>p</i> <i>a</i> <i>b</i> <i>c</i>))
(when <i>p</i> <i>a</i> <i>b</i> <i>c</i>) == (if <i>p</i> (progn <i>a</i> <i>b</i> <i>c</i>) <tt>nil</tt>)
(when <i>p</i> <i>a</i> <i>b</i> <i>c</i>) == (unless (not <i>p</i>) <i>a</i> <i>b</i> <i>c</i>)
</pre><P>
As a matter of style,
<tt>when</tt> is normally used to conditionally produce some side effects,
and the value of the <tt>when</tt> form is normally not used.
If the value is relevant, then it may be
stylistically more appropriate to use <tt>and</tt> or <tt>if</tt>.
<P>
<BR><b>[Macro]</b><BR>
<tt>unless <i>test</i> {<i>form</i>}*</tt><P><tt>(unless <i>test</i> <i>form1</i> <i>form2</i> ... )</tt>
first evaluates <i>test</i>. If the result is <i>not</i> <tt>nil</tt>,
then the <i>form</i>s are not evaluated, and <tt>nil</tt> is returned.
Otherwise the <i>form</i>s constitute an implicit <tt>progn</tt>
and are evaluated sequentially from left to right,
and the value of the last one is returned.
<P><pre>
(unless <i>p</i> <i>a</i> <i>b</i> <i>c</i>) == (cond ((not <i>p</i>) <i>a</i> <i>b</i> <i>c</i>))
(unless <i>p</i> <i>a</i> <i>b</i> <i>c</i>) == (if <i>p</i> <tt>nil</tt> (progn <i>a</i> <i>b</i> <i>c</i>))
(unless <i>p</i> <i>a</i> <i>b</i> <i>c</i>) == (when (not <i>p</i>) <i>a</i> <i>b</i> <i>c</i>)
</pre><P>
As a matter of style,
<tt>unless</tt> is normally used to conditionally produce some side effects,
and the value of the <tt>unless</tt> form is normally not used.
If the value is relevant, then it may be
stylistically more appropriate to use <tt>if</tt>.
<P>
<BR><b>[Macro]</b><BR>
<tt>cond {(<i>test</i> {<i>form</i>}*)}*</tt><P>A <tt>cond</tt> form has a number (possibly zero) of
<i>clauses</i>, which are lists of forms.
Each clause consists of a <i>test</i> followed
by zero or more <i>consequents</i>.
For example:
<P><pre>
(cond (<i>test-1</i> <i>consequent-1-1</i> <i>consequent-1-2</i> ...)
(<i>test-2</i>)
(<i>test-3</i> <i>consequent-3-1</i> ...)
... )
</pre><P>
<P>
The first clause whose <i>test</i> evaluates to non-<tt>nil</tt>
is selected; all other clauses are ignored, and the consequents
of the selected clause are evaluated in order (as an implicit <tt>progn</tt>).
<P>
More specifically, <tt>cond</tt> processes its clauses in order from left to
right. For each clause, the <i>test</i> is evaluated. If the result is
<tt>nil</tt>, <tt>cond</tt> advances to the next clause. Otherwise, the <i>cdr</i> of
the clause is treated as a list of forms, or consequents; these forms are
evaluated in order from left to right, as an implicit <tt>progn</tt>.
After evaluating the consequents,
<tt>cond</tt> returns without inspecting any remaining clauses.
The <tt>cond</tt> special form returns the results
of evaluating the last of the selected consequents;
if there were no consequents in
the selected clause,
then the single (and necessarily non-null) value of the <i>test</i> is returned.
If <tt>cond</tt> runs out of clauses (every test produced <tt>nil</tt>,
and therefore no clause was selected), the value of the <tt>cond</tt> form is
<tt>nil</tt>.
<P>
If it is desired to select the last clause unconditionally if all others
fail, the standard convention is to use <tt>t</tt> for the <i>test</i>.
As a matter of style, it is desirable to write a last clause
<tt>(<tt>t</tt> <tt>nil</tt>)</tt> if the value of the <tt>cond</tt> form is to be used
for something. Similarly, it is in questionable
taste to let the last clause of
a <tt>cond</tt> be a ``singleton clause''; an explicit <tt>t</tt> should be provided.
(Note moreover that <tt>(cond ... (<i>x</i>))</tt> may behave differently from
<tt>(cond ... (<tt>t</tt> <i>x</i>))</tt> if <i>x</i> might produce multiple values;
the former always returns a single value, whereas the latter returns whatever
values <i>x</i> returns. However, as a matter of style it is preferable
to obtain this behavior by writing <tt>(cond ... (t (values <i>x</i>)))</tt>,
using the <tt>values</tt> function explicitly to indicate the discarding
of any excess values.)
For example:
<P><pre>
(setq z (cond (a 'foo) (b 'bar))) ;Possibly confusing
(setq z (cond (a 'foo) (b 'bar) (t nil))) ;Better
(cond (a b) (c d) (e)) ;Possibly confusing
(cond (a b) (c d) (t e)) ;Better
(cond (a b) (c d) (t (values e))) ;Better (if one value
; needed)
(cond (a b) (c)) ;Possibly confusing
(cond (a b) (t c)) ;Better
(if a b c) ;Also better
</pre><P>
A Lisp <tt>cond</tt> form may be compared to a continued <b>if</b>-<b>then</b>-<b>else</b>
as found in many algebraic programming languages:
<P><pre>
(cond (<i>p</i> ...) <b>if</b> <i>p</i> <b>then</b> ...
(<i>q</i> ...) roughly <b>else</b> <b>if</b> <i>q</i> <b>then</b> ...
(<i>r</i> ...) corresponds <b>else</b> <b>if</b> <i>r</i> <b>then</b> ...
... to ...
(<tt>t</tt> ...)) <b>else</b> ...
</pre><P>
<P>
<BR><b>[Macro]</b><BR>
<tt>case</tt> <tt><i>keyform</i></tt> <tt>{({({<i>key</i>}*)</tt> <tt>|</tt> <tt><i>key</i>}</tt> <tt>{<i>form</i>}*)}*</tt><P><tt>case</tt> is a conditional that chooses one of its clauses to execute
by comparing a value to various constants, which are
typically keyword symbols, integers, or characters
(but may be any objects). Its form is as follows:
<P><pre>
(case <i>keyform</i>
(<i>keylist-1</i> <i>consequent-1-1</i> <i>consequent-1-2</i> ...)
(<i>keylist-2</i> <i>consequent-2-1</i> ...)
(<i>keylist-3</i> <i>consequent-3-1</i> ...)
...)
</pre><P>
Structurally <tt>case</tt> is much like <tt>cond</tt>,
and it behaves like <tt>cond</tt>
in selecting one clause and then executing all consequents of that clause.
However, <tt>case</tt> differs in the mechanism of clause selection.
<P>
The first thing <tt>case</tt> does is to evaluate the form <i>keyform</i>
to produce an object called the <i>key object</i>.
Then <tt>case</tt> considers
each of the clauses in turn. If <i>key</i> is in the <i>keylist</i>
(that is, is <tt>eql</tt> to any item in the <i>keylist</i>) of a clause,
the consequents of that
clause are evaluated as an implicit <tt>progn</tt>;
<tt>case</tt> returns what was returned by the last
consequent (or <tt>nil</tt> if there are no consequents in that clause).
If no clause is satisfied, <tt>case</tt> returns <tt>nil</tt>.
<P>
The keys in the keylists are <i>not</i> evaluated; literal key values
must appear in the keylists.
It is an error for the same key to appear in more than one clause;
a consequence is that the order of the clauses does not affect
the behavior of the <tt>case</tt> construct.
<P>
Instead of a <i>keylist</i>, one may write one of the symbols
<tt>t</tt> and <tt>otherwise</tt>. A clause with such a symbol
always succeeds and must be the last clause (this is an exception
to the order-independence of clauses).
See also <tt>ecase</tt> and <tt>ccase</tt>, each of which provides
an implicit <tt>otherwise</tt> clause to signal an error if no clause
is satisfied.
<P>
If there is only one key for a clause, then that key may be written
in place of a list of that key, provided that no ambiguity results.
Such a ``singleton key'' may not be <tt>nil</tt> (which is confusable
with <tt>()</tt>, a list of no keys), <tt>t</tt>, <tt>otherwise</tt>, or a cons.
<P>
<hr>
<b>Compatibility note:</b> The Lisp Machine Lisp <tt>caseq</tt> construct
uses <tt>eq</tt> for the comparison.
In Lisp Machine Lisp <tt>caseq</tt> therefore works for
fixnums but not bignums.
The MacLisp <tt>caseq</tt> construct simply prohibits the use of bignums;
indeed, it permits only fixnums and symbols as clause keys.
In the interest of hiding the fixnum-bignum distinction,
and for general language consistency,
<tt>case</tt> uses <tt>eql</tt> in Common Lisp.
<P>
The Interlisp <tt>selectq</tt> construct is similar to <tt>case</tt>.
<hr>
<P>
<BR><b>[Macro]</b><BR>
<tt>typecase</tt> <tt><i>keyform</i></tt> <tt>{(<i>type</i></tt> <tt>{<i>form</i>}*)}*</tt><P><tt>typecase</tt> is a conditional that chooses one of its clauses by
examining the type of an object.
Its form is as follows:
<P><pre>
(typecase <i>keyform</i>
(<i>type-1</i> <i>consequent-1-1</i> <i>consequent-1-2</i> ...)
(<i>type-2</i> <i>consequent-2-1</i> ...)
(<i>type-3</i> <i>consequent-3-1</i> ...)
...)
</pre><P>
Structurally <tt>typecase</tt> is much like <tt>cond</tt> or <tt>case</tt>,
and it behaves like them
in selecting one clause and then executing all consequents of that clause.
It differs in the mechanism of clause selection.
<P>
The first thing <tt>typecase</tt> does is to evaluate the form <i>keyform</i>
to produce an object called the key object.
Then <tt>typecase</tt> considers
each of the clauses in turn. The <i>type</i> that appears
in each clause is a type specifier; it is not evaluated
but is a literal type specifier.
The first clause for which the key
is of that clause's specified <i>type</i>
is selected, the consequents of this
clause are evaluated as an implicit <tt>progn</tt>,
and <tt>typecase</tt> returns what was returned by the last
consequent (or <tt>nil</tt> if there are no consequents in that clause).
If no clause is satisfied, <tt>typecase</tt> returns <tt>nil</tt>.
<P>
As for <tt>case</tt>, the symbol <tt>t</tt> or <tt>otherwise</tt> may be written
for <i>type</i> to indicate that the clause should always be selected.
See also <tt>etypecase</tt> and <tt>ctypecase</tt>, each of which provides
an implicit <tt>otherwise</tt> clause to signal an error if no clause
is satisfied.
<P>
It is permissible for more than one clause to specify a given type,
particularly if one is a subtype of another; the earliest applicable
clause is chosen. Thus for <tt>typecase</tt>, unlike <tt>case</tt>, the order
of the clauses may affect the behavior of the construct.
For example:
<P><pre>
(typecase an-object
(string ...) ;This clause handles strings
((array t) ...) ;This clause handles general arrays
((array bit) ...) ;This clause handles bit arrays
(array ...) ;This handles all other arrays
((or list number) ...) ;This handles lists and numbers
(t ...)) ;This handles all other objects
</pre><P>
A Common Lisp compiler may choose to issue a warning if
a clause cannot be selected because it is completely shadowed by
earlier clauses.
<P>
<BR> <HR><A NAME=tex2html2572 HREF="node85.html"><IMG ALIGN=BOTTOM ALT="next" SRC="icons/next_motif.gif"></A> <A NAME=tex2html2570 HREF="node76.html"><IMG ALIGN=BOTTOM ALT="up" SRC="icons/up_motif.gif"></A> <A NAME=tex2html2564 HREF="node83.html"><IMG ALIGN=BOTTOM ALT="previous" SRC="icons/previous_motif.gif"></A> <A NAME=tex2html2574 HREF="node1.html"><IMG ALIGN=BOTTOM ALT="contents" SRC="icons/contents_motif.gif"></A> <A NAME=tex2html2575 HREF="index.html"><IMG ALIGN=BOTTOM ALT="index" SRC="icons/index_motif.gif"></A> <BR>
<B> Next:</B> <A NAME=tex2html2573 HREF="node85.html"> Blocks and Exits</A>
<B>Up:</B> <A NAME=tex2html2571 HREF="node76.html"> Control Structure</A>
<B> Previous:</B> <A NAME=tex2html2565 HREF="node83.html"> Establishing New Variable </A>
<HR> <P>
<HR>
<P><ADDRESS>
AI.Repository@cs.cmu.edu
</ADDRESS>
</BODY>