是否可以使用Clojure的case表单与Java枚举? [英] Is it possible to use Clojure's case form with a Java enum?
问题描述
案例
doc说
与cond和condp不同,case恒定时间分派...所有方式的常数
表达式都是可以接受的。
Unlike cond and condp, case does a constant-time dispatch... All manner of constant expressions are acceptable in case.
case
的常量分派以匹配Java枚举。 Java的 switch
语句适用于枚举,但在Clojure中执行以下操作:
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)
结果: IllegalArgumentException没有匹配的子句:MILLISECONDS
Results in: IllegalArgumentException No matching clause: MILLISECONDS
case
中是否不支持枚举?我做错了什么?我必须诉诸 cond
还是有更好的解决方案?
Are enums not supported in case
? Am I doing something wrong? Must I resort to cond
or is there a better solution?
推荐答案
这里的问题是 case
的测试常量,如文档中所述,必须是编译时文字。所以,不是解析 java.util.concurrent.TimeUnit / MILLISECONDS
,文字符号'java.util.concurrent.TimeUnit / MILLISECONDS
正在测试。
The problem here is that case
's test constants, as described in the docs, " must be compile-time literals". So, rather than resolving java.util.concurrent.TimeUnit/MILLISECONDS
, the literal symbol 'java.util.concurrent.TimeUnit/MILLISECONDS
is being tested against.
(foo java.util.concurrent.TimeUnit/MILLISECONDS) ; IllegalArgumentException
(foo 'java.util.concurrent.TimeUnit/MILLISECONDS) ; yes!
相反,解决方案是在 .ordinal
的 Enum
实例,这是Java本身在编译 switch
语句时枚举:
Instead, the solution is to dispatch on the .ordinal
of the Enum
instance, which is what Java itself does when compiling switch
statements over enums:
(defn foo [x]
(case (.ordinal x)
2 "yes!"))
您可以将此模式包装在正确评估用例序号的宏中:
You can wrap this pattern in a macro which correctly evaluates the case ordinals for you:
(defmacro case-enum
"Like `case`, but explicitly dispatch on Java enum ordinals."
[e & clauses]
(letfn [(enum-ordinal [e] `(let [^Enum e# ~e] (.ordinal e#)))]
`(case ~(enum-ordinal e)
~@(concat
(mapcat (fn [[test result]]
[(eval (enum-ordinal test)) result])
(partition 2 clauses))
(when (odd? (count clauses))
(list (last clauses)))))))
这篇关于是否可以使用Clojure的case表单与Java枚举?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!