Co

# Conditionals in

24 exercises

Common Lisp provides the programmer with several different conditionals that can be categorised by the number of "branches" they support.

Also, unlike many other programming languages, all conditionals in Common Lisp are expressions not statements. This means that all Lisp conditionals evaluate to some value and can be substituted for concrete parameters.

As an example:

``````;; Doubles x when it's even
(* x (if (evenp x) 2 1))
``````

### Single-Branch Conditionals

The conditionals `when` and `unless` evaluate some code only when the provided test is true or false respectively â€“ evaluating to `nil` otherwise.

The section after the test expression may be more than one expression.

``````(when (= 2 2) "All is well")      ; => "All is well"
(unless (= 2 2) "Time to panic!") ; => NIL
``````

### The Two-Branch Conditional

The `if` conditional evaluates the first expression of the body when the test is true and the second one otherwise.

``````(if (= 2 2) 'how-honest 'you-liar) ; => HOW-HONEST
``````

Note that both the then and else clauses can only be a single expression.

### Many-Branch Conditionals

The Lisp "super-conditional" is `cond`, which can have an infinite number of branches. Each branch has a test condition and body expression that are surrounded by an extra pair of parentheses. If all of the tests evaluate to false, then `nil` is returned.

``````(cond ((= 0 2) 'nope)
((= 1 2) 'try-again)
((= 2 2) 'quite-true)
((= 3 2) 'too-far)
(t 'something-else))
; => QUITE-TRUE
``````

Note that there is no limit to the number of expressions after the test expression.

If you just want to test one value against a number of branches, you can use the cleaner `case` expression. If none of the cases match, `nil` is returned. Both `t` and `otherwise` can be used as catch-all cases:

``````(case 'elder-beast
(cat "Meow")
(bird "Chirp")
(dog "Bark")
(otherwise "???"))
; => "???"
``````

Note that like `cond` there is no limit to the number of expressions after the test expression.

### The Stealth Conditionals

The boolean `and` and `or` operations in Common Lisp are short-circuiting macros that can be used to reduce the duplication of certain conditional expressions.

The `and` macro will immediately return `nil` if a single false value is encountered, but the last true value of the `and` otherwise:

``````(and 42 "Magic" :cool) ; => :COOL
(and () "Magic" :cool) ; => NIL
``````

The `or` macro returns the first true value it encounters or `nil` if there were no true values:

``````(or () 42 nil)  ; => 42
(or () NIL nil) ; => NIL
``````

### I'm Exhausted...

As mentioned previously, when none of the branches in a `case` statement match, and there is no `otherwise` clause, `nil` is returned. Occasionally, however, a failure to match any branch should be treated as an error â€“ this is where `ecase` (for exhaustive matching) comes in.

It's used in exactly the same way as `case`, but signals an error instead of returning `nil` when there is no match.

``````(case 'elder-beast
(cat "Meow")
(bird "Chirp")
(dog "Bark"))
; => NIL

(ecase 'elder-beast
(cat "Meow")
(bird "Chirp")
(dog "Bark"))
; => ERROR: ELDER-BEAST fell through ECASE expression. Wanted one of (CAT BIRD DOG).
``````
Edit via GitHub