我们可以在 Clojure 中使用宏静态分派 return 类型吗?

Can we use macros to statically dispatch on a return type in Clojure?

现在我们知道了 Clojure 协议上的调度,

我们在这里看到 compile-time dispatch 使用宏的精彩示例:

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

此处 the writer argues 您将永远无法在 return 类型上调度 Clojure。在我看来,有了足够强大的宏,您就可以做任何事情。

我的问题是:我们可以在 Clojure 中使用宏静态分派 return 类型吗?

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

但是,从实际的角度来看,在 return 类型上分派编译类型意味着使此信息可用并在编译时传播它。 Clojure 中没有内置 'return type'(所有函数都接受可变数量的对象类型参数和 return 一个对象),因此您可能不得不推出自己的类型系统并需要大量您的部分程序参与其中(à la Type Clojure),但类型分析必须在您使用宏后立即可用。

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