Up: Conditional Execution   [Contents][Index]


15.25.10.1 if - when - unless

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]
when
if

The constructs ‘when19 and ‘if’ allow conditional execution of loop clauses. These constructs are synonyms and can be used interchangeably.

expr
non-nil

If the value of the test expression expr is non-nil, the expression clause1 is evaluated.

nil

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.

unless

construct is equivalent to when (not expr) and if (not expr).20

nil

If the value of the test expression expr is nil, the expression clause1 is evaluated.

non-nil

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.

Clause Argument Types

The clause arguments must be either

Compound Clauses

Clauses that follow the test expression can be grouped by using the loop keyword ‘and’ to produce a compound clause.

Referring to the Result of the Test Expression using “it”

it

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.

Nesting Clauses and “else”

If ‘when’ or ‘if’ clauses are nested, each ‘else’ is paired with the closest preceding ‘when’ or ‘if’ construct that has no associated else.

Marking the End of the Conditional Clauses

end

optional loop keyword 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.

Examples

;;; 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)
;;; Find a number in a list.
(loop for i in '(1 2 3 4 5 6)
      when (and (> i 3) i)
      return it)
;; The preceding example is similar to the following one.
(loop for i in '(1 2 3 4 5 6)
      thereis (and (> i 3) i))
;;; 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"))

Footnotes

(19)

[Compare this to the macro when, which does not allow an “else” part.-GLS]

(20)

[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]


Up: Conditional Execution   [Contents][Index]