Browse Clojure Foundations for Java Developers

Conditional Macros

Everyday branching tools beyond if: when, if-let/when-let, cond, and case (plus the truthiness rules that matter).

In Clojure, most “control structures” are macros built on top of a small set of special forms. The goal is not to memorize them all, but to recognize the ones you’ll read constantly.

One truthiness rule matters everywhere:

  • only false and nil are falsey
  • everything else is truthy (including 0, "", [], {})

when / when-not (Side-Effect-Friendly Branching)

Use when when you only need the “then” branch:

1(when (pos? n)
2  (println "positive")
3  (inc n))

It evaluates to the last expression in the body, or nil if the condition is false.

when-not is the negated version.

if-let / when-let (Bind and Check in One Step)

These are idiomatic for nil-checking while naming the value:

1(if-let [email (:email user)]
2  (send-email! email)
3  (println "User has no email"))
  • if the binding is truthy, the name is available in the “then” branch
  • otherwise you fall through to “else” (or nil for when-let)

cond (Multi-Branch)

cond is the “ladder” form when you have multiple tests:

1(cond
2  (nil? x)  :missing
3  (neg? x)  :negative
4  :else     :ok)

case (Fast Dispatch on Constants)

Use case when you’re matching against constants (similar to a Java switch):

1(case status
2  :ok    200
3  :fail  500
4  400) ; default

Knowledge Check: Conditionals

### What does `when` return when the condition is false? - [x] `nil` - [ ] `false` - [ ] It throws - [ ] The original condition > **Explanation:** `when` has no else branch. If the test is falsey, it returns `nil`. ### In `(if-let [v (lookup k)] ...)`, what is `v` bound to in the “then” branch? - [x] The result of `(lookup k)` (only if it is truthy) - [ ] Always `true` - [ ] The keyword `:v` - [ ] A Java Optional > **Explanation:** `if-let` both binds and tests. The “then” branch runs only when the bound value is truthy. ### What does `cond` do? - [x] Evaluates tests top-to-bottom and returns the expression for the first truthy test. - [ ] Evaluates all branches and returns the last. - [ ] Only works for numeric comparisons. - [ ] Is the same as `case`. > **Explanation:** `cond` is the multi-branch conditional. `:else` is just a convention for a final always-true test.
Revised on Friday, April 24, 2026