The case
doc says
Unlike cond and condp, case does a constant-time dispatch... All manner of constant expressions are acceptable in case.
I would like to benefit from case
's constant-time dispatch to match on Java enums. Java's switch
statement works well with enums, but doing the following in Clojure:
(defn foo [x]
(case x
java.util.concurrent.TimeUnit/MILLISECONDS "yes!"))
(foo java.util.concurrent.TimeUnit/MILLISECONDS)
Results in: IllegalArgumentException No matching clause: MILLISECONDS
Are enums not supported in case
? Am I doing something wrong? Must I resort to cond
or is there a better solution?
The problem here is that
case
's test constants, as described in the docs, " must be compile-time literals". So, rather than resolvingjava.util.concurrent.TimeUnit/MILLISECONDS
, the literal symbol'java.util.concurrent.TimeUnit/MILLISECONDS
is being tested against.Instead, the solution is to dispatch on the
.ordinal
of theEnum
instance, which is what Java itself does when compilingswitch
statements over enums:You can wrap this pattern in a macro which correctly evaluates the case ordinals for you:
You could use use a cond on the name of the enumm
(case (.name myEnumValue) "NAME_MY_ENUM" (println "Hey, it works!"))
Seems to me very simple compared to the alternatives
Here's a simpler solution that just uses equality checking on the cases -