此代码不是我的"真实"代码,但是从更大的算法的问题的样本。我花了一段时间才找到((set! *warn-on-reflection* true)
)反射是问题。
随着类型提示进入动态语言(例如python和clojure)以及侵略性类型引用传递给其他人(例如Scala),我必须明确地使用(int ...)
进行强制转换。
为什么不知道(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
我知道类型提示与此int
调用的输入并不相同,但在更复杂的代码中可能并非如此。
答案 0 :(得分:7)
注意:从Clojure 1.8.0开始手动测试
为什么不知道(aget int-array int)返回一个int?
确实如此。它似乎不知道的是(if <<condition>> Long int)
返回一个可以强制转换为原始int的结果。请注意,如果您改为编写(int 40)
,反射警告就会消失。
我可以自己注释if语句,说它返回一个int吗?
使用(int ...)
确实是这样做的方法。在这种情况下,int类型提示不正确,因为我们已经看到这个表达式可能会返回一个long。
随着类型提示进入动态语言(例如python和clojure)以及侵略性类型引用传递给其他人(例如Scala),我似乎很奇怪我必须明确地使用(int ...)
Clojure本质上是一种动态类型语言。 Clojure编译器已经进行了相当多的类型推断 - 特别是在本地 - 但仍然是尽力而为,我不认为应该预期其他任何事情(请记住,不知道在程序中流动的值的类型是动态类型的特征。当然,你粘贴的特定代码片段可以进行相当多的静态分析,但是在一个典型的现实世界的程序中,价值流经很多中介,这种广泛的分析甚至是不可行的 - 因此,为什么编译器会竭尽全力支持它呢?