280 lines
14 KiB
HTML
280 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>
|