Common Lisp the Language, 2nd Edition
Next: Unconditional
Execution Up: Loop
Previous: Variable
Initializations
The loop keywords if
, when
, and
unless
designate constructs that are useful when you want
some loop clauses to operate under a specified condition.
If the specified condition is true, the succeeding loop clause is
executed. If the specified condition is not true, the succeeding clause
is skipped, and program control moves to the clause that follows the
loop keyword else
. If the specified condition is not true
and no else
clause is specified, the entire conditional
construct is skipped. Several clauses can be connected into one compound
clause with the loop keyword and
. The end of the
conditional clause can be marked with the keyword end
.
[Loop Clause]
if expr clause {and clause}*
[else clause {and clause}*] [end]
when expr clause {and clause}*
[else clause {and clause}*] [end]
unless expr clause {and clause}*
[else clause {and clause}*] [end]
The constructs when
and if
allow
conditional execution of loop clauses. These constructs are synonyms and
can be used interchangeably. [Compare this to the macro
when
, which does not allow an ``else’’ part.-GLS]
If the value of the test expression expr is
non-nil
, the expression clause1 is evaluated. If
the test expression evaluates to nil
and an
else
construct is specified, the statements that follow the
else
are evaluated; otherwise, control passes to the next
clause.
The unless
construct is equivalent to when
(not
expr) and if
(not
expr). If the value of the test expression expr is
nil
, the expression clause1 is evaluated. If the
test expression evaluates to non-nil
and an
else
construct is specified, the statements that follow the
else
are evaluated; otherwise, control passes to the next
clause. [Compare this to the macro unless
, which
does not allow an ``else’’ part-or do I mean a ``then’’ part?! Ugh. To
prevent confusion, I strongly recommend as a matter of style that
else
not be used with unless
loop
clauses.-GLS]
The clause arguments must be either accumulation,
unconditional, or conditional clauses (see section 26.3.2). Clauses that follow
the test expression can be grouped by using the loop keyword
and
to produce a compound clause.
The loop keyword it
can be used to refer to the result
of the test expression in a clause. If multiple clauses are connected
with and
, the it
construct must be used in the
first clause in the block. Since it
is a loop keyword,
it
may not be used as a local variable within a loop.
If when
or if
clauses are nested, each
else
is paired with the closest preceding when
or if
construct that has no associated
else
.
The optional loop keyword end
marks the end of the
clause. If this keyword is not specified, the next loop keyword marks
the end. You can use end
to distinguish the scoping of
compound clauses.
;;; Group conditional clauses into a block.
(loop for i in numbers-list
when (oddp i)
do (print i)
and collect i into odd-numbers
and do (terpri)
else ;I is even
collect i into even-numbers
finally
(return (values odd-numbers even-numbers)))
;;; Collect numbers larger than 3.
(loop for i in '(1 2 3 4 5 6)
when (and (> i 3) i)
collect it) ;it refers to (and (> i 3) i)
=> (4 5 6)
;;; Find a number in a list.
(loop for i in '(1 2 3 4 5 6)
when (and (> i 3) i)
return it)
=> 4
;;; The preceding example is similar to the following one.
(loop for i in '(1 2 3 4 5 6)
thereis (and (> i 3) i))
=> 4
;;; An example of using UNLESS with ELSE (yuk).`-GLS
(loop for turtle in teenage-mutant-ninja-turtles do
(loop for x in '(joker brainiac shredder krazy-kat)
unless (evil x)
do (eat (make-pizza :anchovies t))
else unless (and (eq x 'shredder) (attacking-p x))
do (cut turtle slack);When the evil Shredder attacks,
else (fight turtle x)));those turtle boys don't cut no slack
;;; Nest conditional clauses.
(loop for i in list
when (numberp i)
when (bignump i)
collect i into big-numbers
else ;Not (bignump i)
collect i into other-numbers
else ;Not (numberp i)
when (symbolp i)
collect i into symbol-list
else ;Not (symbolp i)
(error "found a funny value in list ~S, value ~S~%"
"list i))
;;; Without the END marker, the last AND would apply to the
;;; inner IF rather than the outer one.
(loop for x from 0 to 3
do (print x)
if (zerop (mod x 2))
do (princ " a")
and if (zerop (floor x 2))
do (princ " b")
end
and do (princ " c"))
Next: Unconditional
Execution Up: Loop
Previous: Variable
Initializations
AI.Repository@cs.cmu.edu