类型推理的Clojure不足

Phi*_*per 2 type-inference clojure

这段代码不是我的"真实"代码,而是来自更大算法的问题示例.在我发现(set! *warn-on-reflection* true)反射是问题之前我花了一段时间.

随着类型提示变为动态语言(例如python和clojure)以及侵略性类型引用传递给其他人(例如Scala),我必须明确地使用(int ...).

为什么clojure不知道(aget int-array int)返回int?

我可以自己注释if语句,说它返回一个int吗?

如果没有,我可以使用内联函数来避免重新感染.

(let [a (int-array [4 5 6 7])]
   ;(aset a 1 (int (if (seq a) 40 (aget a 0))))) ;; fast
    (aset a 1      (if (seq a) 40 (aget a 0))))  ;; slow
Run Code Online (Sandbox Code Playgroud)

我知道类型提示并不比这个int调用更简单,但在更复杂的代码中可能并非如此.

Val*_*nck 8

注意:从Clojure 1.8.0开始手动测试

为什么clojure不知道(aget int-array int)返回一个int?

确实如此.它似乎不知道的是(if <<condition>> Long int)返回一个可以强制转换为原始int的结果.请注意,如果您(int 40)改为编写,反射警告就会消失.

我可以自己注释if语句,说它返回一个int吗?

使用(int ...)真的是这样做的方式.在这种情况下,int类型提示不正确,因为我们已经看到这个表达式可能返回long.

随着类型提示进入动态语言(例如python和clojure)和侵略性类型引用到其他人(例如Scala),我必须明确地使用(int ...)强制转换

Clojure本质上是一种动态类型语言.Clojure编译器已经进行了相当多的类型推断 - 特别是在本地 - 但仍然是在尽力而为的基础上,我不认为应该预期任何其他事情(请记住,不知道流动的值的类型程序周围是动态类型的一个特征).当然,你粘贴的特定代码片段可以进行相当多的静态分析,但在一个典型的真实世界程序中,价值流经很多中介,这种广泛的分析甚至是不可行的 - 因此,为什么编译器是否会竭尽全力支持它?