现在我们知道,严格来说,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 中对返回类型进行静态调度吗?
从理论上讲,你可以使用宏来构建一个具有Haskell类型语义的Clojure DSL,所以是的,严格来说这是可能的。
但是,从实际的角度来看,在编译类型上对返回类型进行调度意味着使此信息可用并在编译时传播它。Clojure 中没有内置的"返回类型"(所有函数都接受可变数量的 Object 类型参数并返回一个 Object),因此您可能必须推出自己的类型系统并要求大部分程序参与其中(类似于 Type Clojure),但约束是一旦使用宏,类型分析必须可用。
case+
(双关语)的情况有所不同,因为它不需要类型系统,主要是评估顺序的问题。