38

Is there an equivalent for Java's switch construct in Clojure? If yes, what is it? If no, do we have to use if else ladder to achieve it?

omiel
  • 1,573
  • 13
  • 16
vikbehal
  • 1,486
  • 3
  • 21
  • 48

3 Answers3

42

case is a good option as pointed out by Jan

cond is also very useful in many related circumstances, particularly if you want to switch on the basis of evaluating a range of different conditional expressions, e.g.

(defn account-message [balance]
  (cond 
    (< balance 0) "Overdrawn!"
    (< balance 100) "Low balance"
    (> balance 1000000) "Rich as creosote"
    :else "Good balance"))

Note that the result of cond is determined by the first matching expression, so a negative balance will display "Overdrawn!" even though it also matches the low balance case.

[I have edited the code - removed the extra bracket at the end to make it work]

monojohnny
  • 5,894
  • 16
  • 59
  • 83
mikera
  • 105,238
  • 25
  • 256
  • 415
41

Try the case macro:

(case (+ 2 3)
  6 "error"
  5 "ok")

or with default value

(case (+ 2 3)
  5 "ok"
  "error")

Remember that according to the documentation

The test-constants are not evaluated. They must be compile-time literals, and need not be quoted. (...)

See more examples at ClojureDocs.

Jan
  • 11,636
  • 38
  • 47
  • 6
    If your test values are non-literals, you might also want to look into `condp`: `(condp = (+ 2 3) (inc 4) "Ok" (dec 7) "error")`. – kotarak Dec 02 '11 at 07:00
  • @Jan Using `case` of clojure is slowing down the process (noticeable time), is there any other alternative? – vikbehal Dec 02 '11 at 11:34
  • @vikbehal, there's also `cond`, as pointed out in mikera's answer. I'm really interested to learn what might be the cause of this slowdown. Could you do some research, e.g. profiling, and share the results? – Jan Dec 02 '11 at 14:20
8

Though @Jan and @mikera suggestions to use case or cond (may I add condp to the list?) are sound from a functional¹ standpoint and though case 's limitations (e.g. test values can only be compile-time constants ; a default return value is mandatory) mirror those of switch there are some subtle differences:

  • case cannot be used with Java Enum constants ;

  • case 's dispatch is based on hashing AFAIK which makes it comparable to hashmaps in terms of performance ; switch is way faster ;

  • you cannot fall-through with case, which means that you must use other options (condp with value sets ?) to mirror switch 's behaviour.


[¹] not functional as in , functional as in fulfilling a function, serving a purpose.

omiel
  • 1,573
  • 13
  • 16