When is one better than the other? Is one faster than the other or does the only difference is the return of false or nil?
3 Answers
Use if
when you have exactly one truthy and one falsy case and you don't need an implicit do
block. In contrast, when
should be used when you only have to handle the truthy case and the implicit do
. There is no difference in speed, it's a matter of using the most idiomatic style.
(if (my-predicate? my-data)
(do-something my-data)
(do-something-else my-data))
(when (my-predicate? my-data)
(do-something my-data)
(do-something-additionally my-data))
In the if
case, only do-something
will be run if my-predicate?
returns a truthy result, whereas in the when
case, both do-something
and do-something-additionally
are executed.

- 3,419
- 1
- 21
- 32
-
4What if I only have to handle the true case, and no implicit `do` is needed, which is more conventional to use in this case? – damonh Feb 13 '17 at 13:52
-
2Use `when`. The `do` part is an additional good reason to prefer `when` over `if`, not a necessary precondition. – schaueho Feb 18 '17 at 13:32
Use if
when you have two different expressions: for true
clause and for false
clause.
when
and when-not
are useful in two cases:
- when you want to perform one or several (implicit
do
helps here) non-pure operations conditionally; - when you want to evaluate something when some predicate evaluates to
true
(orfalse
in case ofwhen-not
), and returnnil
in opposite case.
only difference is the return of false or nil
There is no major difference between false
and nil
, as the both evaluate to false
in logical context.

- 7,499
- 2
- 27
- 62
-
1I've noticed a stylistic difference in use of `when` in Clojure and Common Lisp. In CL, some people consider it bad to use `when` if you care about the return value when the test fails; in that case you should explicitly return `nil` in the last clause of an `if`. It makes sense that it's common to use `when` in Clojure in the same situation, since most code is purely functional in Clojure: return values are rarely ignored. If Clojure programmers followed the CL convention, `when` would rarely be used in purely functional code. (Occasionally `nil` vs. `false` matters.) – Mars Sep 21 '14 at 05:55
-
@Mars, it is interesting, is there real reason for coexistence of `false` and `nil` in Clojure? I can think of no situation when `false` could do something that `nil` couldn't. – Mark Karpov Sep 21 '14 at 07:28
-
I think the general idea is: `nil` means "there's nothing left in the sequence", while `false` just means false. The fact that `nil` also means false allows testing for the end of a sequence simply. Also, you can do things like `(get {:a 1 :b nil} :c false)`. More discussion [here](http://stackoverflow.com/questions/5830571/why-did-father-of-clojure-say-that-schemes-true-false-are-broken), [here](http://stackoverflow.com/questions/6045404/why-clojure-idiom-prefer-to-return-nil-instead-of-empty-list-like-scheme), [here](http://www.lispcast.com/nil-punning), and [here](http://clojure.org/lazy). – Mars Sep 22 '14 at 05:23
-
Also: Because `nil` means something like "empty sequence" as well as false, `next` and `rest` have meaning when applied to `nil`, but throw exceptions when applied to `false`. Other interesting uses of `nil` include [`some`](http://clojuredocs.org/clojure_core/clojure.core/some), which can function like a predicate because it returns nil on failure, but isn't really a predicate (therefore it has no "?" in it's name), and [`keep`](http://clojuredocs.org/clojure_core/clojure.core/keep) (see doc page). However, I don't fully understand why Clojure should have both `nil` and `false`. – Mars Sep 22 '14 at 05:40
-
1@Mars In CL, the recommendation is basically the same as for Clojure, cf. https://google-styleguide.googlecode.com/svn/trunk/lispguide.xml#Conditional_Expressions and https://www.cs.cmu.edu/Groups/AI/html/faqs/lang/lisp/part1/faq-doc-4.html. From the latter: _Never use a 2-argument IF or a 3-argument `IF` with a second argument of `NIL` unless you want to emphasize the return value; use `WHEN` and `UNLESS` instead. You will want to emphasize the return value when the IF clause is embedded within a `SETQ`, such as `(SETQ X (IF (EQ Y Z) 2 NIL))`._ – schaueho Sep 22 '14 at 10:20
Since Clojure is still relatively young I think it's worth looking into the much longer history of Lisp practice for guidance here.
Originally when
was to be used if you have a side effect (e.g. see 1, 2 among others). Why? Well it doesn't have an explicit return value in the falsy case implying you don't really care about it, and it also has an implicit do
block (or progn
in Lisp parlor) which only makes sense if you have side effects.
Sometime in the 90s or so the focus shifted though and most guides start to suggest to use when
instead of an if
with only one branch without regards to side effects (for a summary see 3). Why? Well, if you have an if
with only one branch it can leave open the question if you missed to provide the alternative branch or if you even have a misplaced parenthesis. In the best case this can lead to confusion, in the worst case to hidden bugs.
The difference is subtle though, if you rely on the implicit nil
for if
in the falsy case maybe you should make it explicit. Otherwise you probably already rely on a side effect of the truthy branch so when
would be appropriate under both guidances. If your expression is functional and
should be preferred anyway (e.g. see 2), the difference here is that you might get false
instead of nil
in the falsy case though. But again: if you rely on getting nil
why not make it explicit? (In other words: I think linting rules like the example in 4 are misguided.)
Sometimes the rationale for using when
over if
is given as: one should use the most specific construct one needs in the particular case (e.g. see 5). But that same argument can be turned around: don't use when
if you don't need the implicit do
form. So while a good guiding principle in general it can not be really applied here.
So I tend to use when
only when there is a side effect as otherwise there are usually constructs with less imperative smell available (like and
). That is not to say that an if
form should only be used for expressions without side effects, as it might very well be that you need a side effect for both branches.

- 3,568
- 1
- 24
- 36