Ответ 1
Проблема заключается в том, что тестовые константы case
, как описано в документах, должны быть компиляционными литералами времени. Таким образом, вместо разрешения java.util.concurrent.TimeUnit/MILLISECONDS
проверяется литерал 'java.util.concurrent.TimeUnit/MILLISECONDS
.
(foo java.util.concurrent.TimeUnit/MILLISECONDS) ; IllegalArgumentException
(foo 'java.util.concurrent.TimeUnit/MILLISECONDS) ; yes!
Вместо этого решение заключается в отправке на .ordinal
экземпляра Enum
, что и делает сама Java при компиляции операторов switch
над перечислениями:
(defn foo [x]
(case (.ordinal x)
2 "yes!"))
Вы можете обернуть этот шаблон в макрос, который правильно оценивает ординалы дела для вас:
(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)
[email protected](concat
(mapcat (fn [[test result]]
[(eval (enum-ordinal test)) result])
(partition 2 clauses))
(when (odd? (count clauses))
(list (last clauses)))))))