2

现在我们知道 Clojure 协议上的调度,严格来说,是动态的

我们在这里看到了一个使用宏进行编译时调度的绝妙示例:

(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))))

在这里,作者认为您永远无法在 Clojure 中根据返回类型进行调度。对我来说,似乎有了足够强大的宏,你可以做任何事情。

我的问题是:我们可以使用宏在 Clojure 中对返回类型进行静态调度吗?

4

1 回答 1

1

从理论上讲,您可以使用宏来构建具有 Haskell 类型语义的 Clojure DSL,所以严格来说这是可能的。

然而,从实际的角度来看,在编译类型的返回类型上分派意味着使这些信息可用并在编译时传播它。Clojure 中没有内置的“返回类型”(所有函数都接受可变数量的 Object 类型参数并返回一个 Object),因此您可能必须推出自己的类型系统并需要大部分程序来参与其中(à la Type Clojure),约束条件是,一旦使用宏,类型分析就必须可用。

(双关语)的情况case+不同,因为它不需要类型系统,它主要是评估顺序的问题。

于 2016-07-11T12:07:28.633 回答