Clojure 在类型推断方面的不足
Clojure shortfall on type inferencing
此代码不是我的 "real" 代码,而是来自更大算法的问题示例。我花了一段时间才发现((set! *warn-on-reflection* true)
)反射是问题所在。
随着动态语言(例如 python 和 clojure)的类型提示和其他语言(例如 Scala)的激进类型推断,我不得不显式地使用 (int ...)
进行强制转换似乎很奇怪。
为什么 clojure 不知道 (aget int-array int)
returns 一个 int?
我可以自己注释 if 语句说它 returns 一个 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
调用一样,但在更复杂的代码中可能并非如此。
注意:自 Clojure 1.8.0 起手动测试
Why doesn't clojure know that (aget int-array int) returns an int?
确实如此。它似乎不知道 (if <<condition>> Long int)
return 是一个可以被强制转换为原始 int 的结果。请注意,如果您改写 (int 40)
,反射警告就会消失。
Can I annotate the if statement myself to say it returns an int?
使用 (int ...)
确实是做到这一点的方法。这种情况下的 int 类型提示是不正确的,因为正如我们所见,这个表达式可能 return 很长。
With type hinting coming to dynamic languages (e.g. python and clojure) and aggressive type inferencing coming to others (e.g. Scala), it seems odd that I have to explicity cast with (int ...)
Clojure 本质上是一种动态类型语言。 Clojure 编译器已经做了相当多的类型推断——尤其是在本地——但这仍然是在尽力而为的基础上,我认为不应该期待任何其他事情(请记住,不知道流动的值的类型程序周围是动态类型的特征)。诚然,您粘贴的特定代码片段可以进行相当多的静态分析,但在典型的现实世界程序中,值流经许多中介,这种广泛的分析甚至是不可行的 - 因此,为什么编译器应该不遗余力地支持它吗?
此代码不是我的 "real" 代码,而是来自更大算法的问题示例。我花了一段时间才发现((set! *warn-on-reflection* true)
)反射是问题所在。
随着动态语言(例如 python 和 clojure)的类型提示和其他语言(例如 Scala)的激进类型推断,我不得不显式地使用 (int ...)
进行强制转换似乎很奇怪。
为什么 clojure 不知道 (aget int-array int)
returns 一个 int?
我可以自己注释 if 语句说它 returns 一个 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
调用一样,但在更复杂的代码中可能并非如此。
注意:自 Clojure 1.8.0 起手动测试
Why doesn't clojure know that (aget int-array int) returns an int?
确实如此。它似乎不知道 (if <<condition>> Long int)
return 是一个可以被强制转换为原始 int 的结果。请注意,如果您改写 (int 40)
,反射警告就会消失。
Can I annotate the if statement myself to say it returns an int?
使用 (int ...)
确实是做到这一点的方法。这种情况下的 int 类型提示是不正确的,因为正如我们所见,这个表达式可能 return 很长。
With type hinting coming to dynamic languages (e.g. python and clojure) and aggressive type inferencing coming to others (e.g. Scala), it seems odd that I have to explicity cast with (int ...)
Clojure 本质上是一种动态类型语言。 Clojure 编译器已经做了相当多的类型推断——尤其是在本地——但这仍然是在尽力而为的基础上,我认为不应该期待任何其他事情(请记住,不知道流动的值的类型程序周围是动态类型的特征)。诚然,您粘贴的特定代码片段可以进行相当多的静态分析,但在典型的现实世界程序中,值流经许多中介,这种广泛的分析甚至是不可行的 - 因此,为什么编译器应该不遗余力地支持它吗?