Skip to content

clojure.core/case

View this page on ClojureDocs

Type: macro Added: Clojure 1.2 Examples: 8 Runnable: 5
([e & clauses])

Takes an expression, and a set of clauses.

Each clause can take the form of either:

test-constant result-expr

(test-constant1 ... test-constantN) result-expr

The test-constants are not evaluated. They must be compile-time literals, and need not be quoted. If the expression is equal to a test-constant, the corresponding result-expr is returned. A single default expression can follow the clauses, and its value will be returned if no clause matches. If no default expression is provided and no clause matches, an IllegalArgumentException is thrown.

Unlike cond and condp, case does a constant-time dispatch, the clauses are not considered sequentially. All manner of constant expressions are acceptable in case, including numbers, strings, symbols, keywords, and (Clojure) composites thereof. Note that since lists are used to group multiple constants that map to the same expression, a vector can be used to match a list if needed. The test-constants need not be all of the same type.

Examples

by jneira on . May have evaluation errors.
by rmprescott on . May have evaluation errors.
by huahaiy on
by bnii on
by uosl on
by ertugrulcetin on
by Crowbrammer on . May have evaluation errors.
by fdhenard on

Note by dpani

the third example describing myseq may be incorrect. I think we have to use vectors for comparing list of compile time constants.

(let [myseq [1 2]]
 (case myseq
  [] "empty seq"
  [1 2] "my seq"
  "default"))

The parenthesized test conditions are used when multiple test conditions give the same output (output expression). In my case , since both [true, true] and [false, false] return true, i have put them within parenthesis.

(defn equ
 [a b]
 (case [a b]
   ([true true] [false false]) true
   true))

(equ true true) ;; returns true
(equ false false) ;; returns true
(equ false true) ;; return false
(equ true false) ;; returns false

Note by dale

I updated that example with myseq to reflect behavior of Clojure 1.2.0 on my machine. I also added an additional example to explicitly demonstrate multiple values for the same condition.

Note by beluchin

Java enums are not compile-time literals.

Note by eccentric-j

Keep in mind this is not quite like pattern matching.

(case [:a :b]
  [:a :b] "a b combo"
  [_ :b] "at least b" 
)

Will not work. Instead install and use core.match:

(clojure.core.match/match [:a :b]
  [:a :b] "a b combo"
  [_ :b] "at least b")
(Thanks to potetm and Martin Půda on Clojurians Slack)

Note by KingMob

Reminder: compile-time literals are not the same thing as compile-time constants. The Clojure macro/compiler is not smart enough to work with things like Java constants or ^:const vars.

E.g.:

(case Math/PI
  Math/PI :pi
  Math/E :e
  :default)
=> :default



(def ^:const pi Math/PI)
=> #'user/pi
(case Math/PI
  pi :pi
  Math/E :e
  :default)
=> :default

will not work.

See also


Content from the matching ClojureDocs page, with authors credited on each contribution.