在Clojure中,有没有办法使var变为常量,以便可以在case
语句中使用?
e.g。
(def a 1)
(def b 2)
(let [x 1]
(case x
a :1
b :2
:none))
=> :none
我知道我可以使用像cond
或condp
之类的东西来解决这个问题,但如果我能定义一些不需要进一步评估的东西就可以了,所以我可以使用{{1} }。
答案 0 :(得分:2)
Related and answer stolen from it:
正如docstring告诉你的那样:不,你不能这样做。您可以使用Chas Emericks macro并执行此操作:
(defmacro case+
"Same as case, but evaluates dispatch values, needed for referring to
class and def'ed constants as well as java.util.Enum instances."
[value & clauses]
(let [clauses (partition 2 2 nil clauses)
default (when (-> clauses last count (== 1))
(last clauses))
clauses (if default (drop-last clauses) clauses)
eval-dispatch (fn [d]
(if (list? d)
(map eval d)
(eval d)))]
`(case ~value
~@(concat (->> clauses
(map #(-> % first eval-dispatch (list (second %))))
(mapcat identity))
default))))
因此:
(def ^:const a 1)
(def ^:const b 2)
(let [x 1]
(case+ x
a :1
b :2
:none))
=> :1
另一种选择(因为它功能更强大,所以很好)是使用core.match
的功能。虽然您只能匹配本地绑定:
(let [x 2
a a
b b]
(match x
a :1
b :2
:none))
=> :2
答案 1 :(得分:1)
您还可以使用clojure.core/condp
来完成工作:
(def a 1)
(def b 2)
(let [x 1]
(condp = x
a :1
b :2
:none))
#=> :1