为啥 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

类型提示存储为clojure中的元数据?

为啥看似明确的类型提示构造函数调用存在“没有匹配的 ctor”?

Clojure : 类型提示塔

卡在 clojure 中的泛型类类型提示

Clojure 中函数的类型提示