When to use "if" and "when" in Clojure?

10,463

Solution 1

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.

Solution 2

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 (or false in case of when-not), and return nil 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.

Share:
10,463
Alonzorz
Author by

Alonzorz

Updated on June 12, 2022

Comments

  • Alonzorz
    Alonzorz almost 2 years

    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?

  • Mars
    Mars over 9 years
    I'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.)
  • Mark Karpov
    Mark Karpov over 9 years
    @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.
  • Mars
    Mars over 9 years
    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, here, here, and here.
  • Mars
    Mars over 9 years
    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, 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 (see doc page). However, I don't fully understand why Clojure should have both nil and false.
  • schaueho
    schaueho over 9 years
    @Mars In CL, the recommendation is basically the same as for Clojure, cf. google-styleguide.googlecode.com/svn/trunk/… and cs.cmu.edu/Groups/AI/html/faqs/lang/lisp/part1/faq-doc-4.htm‌​l. 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)).
  • damonh
    damonh about 7 years
    What if I only have to handle the true case, and no implicit do is needed, which is more conventional to use in this case?
  • schaueho
    schaueho about 7 years
    Use when. The do part is an additional good reason to prefer when over if, not a necessary precondition.