clojure.core.typed/cf in core.typed 什么时候评估和推断类型
when does clojure.core.typed/cf in core.typed evaluate and infer the type
我不太理解行为或 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)
为什么在这种情况下不计算函数范围,如果它计算了表达式,下面的例子应该return相同的类型:
(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}]
但它们 return 类型不同。
我的直觉是它与 常量 有关,即当我键入检查包含 t/Val 的表单时,然后 core.typed自动评估它。然而,这并不能解释为什么它不对某些功能进行评估。 (range 2)
中的 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))
core.typed
执行完全静态类型检查。
cf
的编译管道是 read -> analyze -> type check -> eval
。
如果存在静态类型错误,则视为致命错误。
否则将执行评估。
(cf (/ 1 0))
抛出运行时错误,因为 (/ 1 0)
是一个类型正确的表达式。
需要原因评估与分析Clojure代码的实用性有关——如果你分析代码而不评估它会发生奇怪的事情。
我不太理解行为或 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)
为什么在这种情况下不计算函数范围,如果它计算了表达式,下面的例子应该return相同的类型:
(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}]
但它们 return 类型不同。
我的直觉是它与 常量 有关,即当我键入检查包含 t/Val 的表单时,然后 core.typed自动评估它。然而,这并不能解释为什么它不对某些功能进行评估。 (range 2)
中的 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))
core.typed
执行完全静态类型检查。
cf
的编译管道是 read -> analyze -> type check -> eval
。
如果存在静态类型错误,则视为致命错误。
否则将执行评估。
(cf (/ 1 0))
抛出运行时错误,因为 (/ 1 0)
是一个类型正确的表达式。
需要原因评估与分析Clojure代码的实用性有关——如果你分析代码而不评估它会发生奇怪的事情。