为啥 Clojure 编译器不会为不正确的类型提示抛出错误?
Posted
技术标签:
【中文标题】为啥 Clojure 编译器不会为不正确的类型提示抛出错误?【英文标题】:Why doesn't the Clojure Compiler throw an error for an incorrect type hint?为什么 Clojure 编译器不会为不正确的类型提示抛出错误? 【发布时间】:2016-04-30 00:51:28 【问题描述】:假设:
我知道类型提示是关于性能优化的,而不是类型检查。我正在尝试解决性能优化何时无效。假设我有以下代码:
(ns test.core)
(defrecord SquarePeg [width length])
(defrecord RoundHole [radius])
(def square-peg (SquarePeg. 5 50))
(defn insert-peg [^test.core.RoundHole peg]
(println "insert-peg inserted with: " peg))
(defn -main
"Insert a square peg in a round hole"
[& args]
(insert-peg square-peg))
当我运行它时,我得到:
insert-peg inserted with: #direct_linking_test.core.SquarePeg:width 5, :length 50
现在我希望这会有 一些 类型提示错误的指示,但事实并非如此。
现在我正在查看Clojure Compiler code - 我看到以下提示处理代码:
hinted arg list emit static value from hinted fields get the class of the hinted field if hinted match method但我没有看到它处理类型提示失败的地方。
我的问题是:为什么 Clojure 编译器不会为不正确的类型提示抛出错误?
【问题讨论】:
【参考方案1】:类型提示大多[1]仅影响本来使用反射的代码——即互操作代码。
由于您的 insert-peg
函数不执行任何互操作,因此类型提示没有用处并且被忽略。
当您的类型提示导致 clojure 编译器编写字节码以调用一种类型的方法时,会发生类型错误,但在运行时实例结果是另一种类型。
[1] 请参阅下面 Alex 评论中的例外情况
【讨论】:
关于提示和错误的快速演示 user=> (.length ^String [1 2 3]) 3 user=> (defn strlen [^String s] (.length s )) #'user/strlen user=> (strlen [1 2 3]) ClassCastException clojure.lang.PersistentVector 不能转换为 java.lang.String user/strlen (NO_SOURCE_FILE:4) 类型提示也可用于创建无需装箱即可采用原始数字参数的函数,尽管在本例中不相关。以上是关于为啥 Clojure 编译器不会为不正确的类型提示抛出错误?的主要内容,如果未能解决你的问题,请参考以下文章
Clojure 类型提示,无法解析类名 clojure.core$double