when, unless
when, unless Macro
Syntax:
when test-form {form}* → {result}*
unless test-form {form}* → {result}*
Arguments and Values:
test-form—a form.
forms—an implicit progn.
results—the values of the forms in a when form if the test-form yields true or in an unless form if the test-form yields false; otherwise nil.
Description:
when and unless allow the execution of forms to be dependent on a single test-form.
In a when form, if the test-form yields true, the forms are evaluated in order from left to right and the values returned by the forms are returned from the when form. Otherwise, if the test-form yields false, the forms are not evaluated, and the when form returns nil.
when, unlessIn an unless form, if the test-form yields false, the forms are evaluated in order from left to right and the values returned by the forms are returned from the unless form. Otherwise, if the test-form yields false, the forms are not evaluated, and the unless form returns nil.
Examples:
(when t ’hello) → HELLO
(unless t ’hello) → NIL
(when nil ’hello) → NIL
(unless nil ’hello) → HELLO
(when t) → NIL
(unless nil) → NIL
(when t (prin1 1) (prin1 2) (prin1 3))
▷ 123
→ 3
(unless t (prin1 1) (prin1 2) (prin1 3)) → NIL
(when nil (prin1 1) (prin1 2) (prin1 3)) → NIL
(unless nil (prin1 1) (prin1 2) (prin1 3))
▷ 123
→ 3
(let ((x 3))
(list (when (oddp x) (incf x) (list x))
(when (oddp x) (incf x) (list x))
(unless (oddp x) (incf x) (list x))
(unless (oddp x) (incf x) (list x))
(if (oddp x) (incf x) (list x))
(if (oddp x) (incf x) (list x))
(if (not (oddp x)) (incf x) (list x))
(if (not (oddp x)) (incf x) (list x))))
→ ((4) NIL (5) NIL 6 (6) 7 (7))
See Also:
and, cond, if, or
Notes:
(when test {form}+) ≡ (and test (progn {form}+))
(when test {form}+) ≡ (cond (test {form}+))
(when test {form}+) ≡ (if test (progn {form}+) nil)
(when test {form}+) ≡ (unless (not test) {form}+)
(unless test {form}+) ≡ (cond ((not test) {form}+))
(unless test {form}+) ≡ (if test nil (progn {form}+))
(unless test {form}+) ≡ (when (not test) {form}+)
Data and Control
Expanded Reference: when, unless
Basic usage of when
when evaluates its body forms only if the test is true, and returns the value of the last body form. If the test is false, it returns NIL without evaluating any body forms.
(when t "hello")
=> "hello"
(when nil "hello")
=> NIL
Basic usage of unless
unless is the opposite of when. It evaluates its body forms only if the test is false.
(unless nil "hello")
=> "hello"
(unless t "hello")
=> NIL
when and unless allow multiple body forms
Unlike if, both when and unless accept multiple body forms (an implicit progn). All forms are evaluated in order and the value of the last is returned.
(when (> 5 3)
(format t "first~%")
(format t "second~%")
"done")
.. first
.. second
..
=> "done"
Using when for one-sided conditionals
when is preferred over if when there is no else branch. It makes the intent clearer.
(defun maybe-print (x)
(when (stringp x)
(format t "Got a string: ~a~%" x)
t))
(maybe-print "hello")
.. Got a string: hello
..
=> T
(maybe-print 42)
=> NIL
Using unless for guard clauses
unless is commonly used for guard clauses and default-value patterns.
(defun safe-divide (a b)
(unless (zerop b)
(/ a b)))
(safe-divide 10 3)
=> 10/3
(safe-divide 10 0)
=> NIL
Side effects and return values
Both when and unless return NIL when they do not execute their body, which makes them useful in conditional side-effect code.
(let ((warnings '()))
(dolist (x '(1 -3 5 -2 0))
(when (minusp x)
(push x warnings)))
warnings)
=> (-2 -3)