何时,core.typed中的clojure.core.typed / cf评估并推断出类型

时间:2015-06-17 10:49:18

标签: clojure clojure-core.typed

我不太了解行为或clojure.core.typed/cf,如下所述。

我假设cf用于推断表单的类型

(t/cf (+ 1 2)) => Long

现在,这失败了

(t/cf (/ 1 0)) => Error

这表明在进行类型检查之前评估了sexpr。我原以为Long

定义自定义函数时:

(t/ann my-fn [t/Any -> t/Num])
(defn my-fn [x]
  (assert (number? x))
  (println "CALLED")
  x)

我可以在同一个表达式中再次使用它,它会失败,表明确实调用了fn。

(t/cf (/ 1 (my-fn 0)) => Error, because it evaluates my-fn. no type inference here??

但是,以下内容对我没有意义。

(t/cf (range)) => (t/ASeq t/AnyInteger)

为什么在这种情况下函数范围没有被评估,如果它确实评估了表达式,下面的例子应该返回相同的类型:

(t/cf (->> (range 2) vec)) =>  (t/AVec (t/U Short Byte Integer BigInteger Long BigInt))
(t/cf [0 1]) =>  [(t/HVec [(t/Val 0) (t/Val 1)]) {:then tt, :else ff}]

但他们会回归不同的类型。

我的直觉是它与常量有关,即当我键入检查包含t / Val的表单时,然后core.typed自动评估它。然而,这并没有解释为什么某些功能不对其进行评估。 2中的(range 2)绝对是一个常数,所以为什么会出现这种差异。

如果在类型检查之前评估表单,则以下内容应具有相同的行为

(t/cf (map inc (range 10))))
(t/cf (map #(inc %) (range 10))))

但是core.typed确实看到了不同之处。第二个示例失败,因为匿名fn默认收到t/Any,您无法在其上调用inc。所以这意味着core.typed必须对表单进行一些分析,并且还对它进行评估。我发现这有点令人困惑,我承认,也许有人可以启发我。

编辑:简短摘要

为什么以下关系在某些情况下似乎并非所有情况都适用?

(t/cf form) <=> (let [x form] (t/cf x))

1 个答案:

答案 0 :(得分:1)

core.typed执行完全静态类型检查。

cf的编译pipleline是read -> analyze -> type check -> eval

如果存在静态类型错误,则认为这是致命的。

否则将进行评估。

(cf (/ 1 0))会抛出运行时错误,因为(/ 1 0)是一个类型很好的表达式。

原因评估需要与分析Clojure代码的实用性相关 - 如果您分析代码然后不对其进行评估,就会发生奇怪的事情。

相关问题