【发布时间】:2015-07-21 14:17:06
【问题描述】:
以下 Clojure 代码实际上是错误的:
(defn divv [x y z] (if (< x y) z (divv ((- x y) y (+ z 1)))))
正确的应该是:
(defn divv [x y z] (if (< x y) z (divv (- x y) y (+ z 1))))
但它通过 Clojure REPL,并返回一个函数。但是当调用它时(例如(divv 3 2 0),就会出现错误
ClassCastException java.lang.Long 无法转换为 clojure.lang.IFn 用户/divv (NO_SOURCE_FILE:1)
问题是,为什么定义divv时没有检测到错误?既然divv已经被定义为一个带3个参数的函数,为什么(divv ((- x y) y (+ z 1)))能通过测试?
【问题讨论】:
-
为什么不能,或者为什么不是?你是在问为什么 Clojure 不做更多的静态分析?
-
因为 Clojure 不是静态语言,并且直到运行时才会进行这种检查。有一个使用附加组件逐步键入的概念,但我不知道这是否扩展到方法签名,或者它如何集成到 REPL 中。
-
可以补充一点,你可以传入特殊设计的参数,使这个函数工作得很好。您可以设计一个允许
-和IFn进行调用的类型。 -
代码的第一个版本没有失败,因为只有一个参数被传递给
divv。如果因为(- x y)返回一个不是IFn的Long 而失败。它从未尝试调用divv。
标签: clojure