core.typed中的clojure.core.typed/cf何时计算并推断类型
我不太理解下面解释的行为或core.typed中的clojure.core.typed/cf何时计算并推断类型,clojure,clojure-core.typed,Clojure,Clojure Core.typed,我不太理解下面解释的行为或clojure.core.typed/cf 我假设cf用于推断表单的类型 (t/cf (+ 1 2)) => Long 现在,这失败了 (t/cf (/ 1 0)) => Error 这向我表明,sexpr是在进行类型检查之前评估的。我原以为很长 定义自定义函数时: (t/ann my-fn [t/Any -> t/Num]) (defn my-fn [x] (assert (number? x)) (println "CALLED")
clojure.core.typed/cf
我假设cf
用于推断表单的类型
(t/cf (+ 1 2)) => Long
现在,这失败了
(t/cf (/ 1 0)) => Error
这向我表明,sexpr是在进行类型检查之前评估的。我原以为很长
定义自定义函数时:
(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)
中的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))
(t/cf格式)(let[x格式](t/cf x))
core.typed
执行完全静态的类型检查
cf
的编译管道是read->analyze->type check->eval
如果存在静态类型错误,则视为致命错误
否则将执行评估
(cf(/10))
抛出运行时错误,因为(/10)
是类型良好的表达式
需要求值的原因与分析Clojure代码的实用性有关——如果分析代码而不求值,就会发生奇怪的事情