使vars保持不变,以便在Clojure

时间:2015-08-30 19:22:45

标签: clojure

在Clojure中,有没有办法使var变为常量,以便可以在case语句中使用?

e.g。

(def a 1)
(def b 2)

(let [x 1]
  (case x
    a :1
    b :2
    :none))
=> :none

我知道我可以使用像condcondp之类的东西来解决这个问题,但如果我能定义一些不需要进一步评估的东西就可以了,所以我可以使用{{1} }。

2 个答案:

答案 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