【问题标题】:Why does this error only show up in the run time in Clojure REPL?为什么这个错误只出现在 Clojure REPL 的运行时?
【发布时间】: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


【解决方案1】:

根据我的经验,语言设计似乎有两种基本的思想流派:

  • School #1(“静态分析”、“Deus Ex Compiler”或“Mad Megalomaniac”学校)认为,检测许多/大多数/所有可能导致在运行时出现问题,其特点是 A) 大量静态类型信息(没有静态数据的静态分析有什么好玩的?),B) 需要消化、筛选和对所有静态数据进行排序,以及 C) 大量编译时错误消息,旨在阻止运行时错误。

  • School #2(“动态分析”、“Nutty 教授”或“Meh - 我们会在运行时弄清楚”学校)认为,因为静态分析无法确定所有可能发生的事情运行时错误(因为有些事情甚至超出了最静态的静态分析的范围 :-) 这不值得费心,而且无论如何都会被洗掉。这些语言/系统的特点是 A) 仅在有限信息上运行的小型编译器,B) 更复杂的运行时支持以检测静态分析可能检测到的错误,C) 最少或没有类型信息,以及 D) 更多运行时错误比你可以摇晃编译器手册。

我自己,我喜欢“动态分析”学派的语言,只是因为它让开发软件变得更有趣。如果您从未使用过变量没有数据类型的语言,并且编译某些东西不一定是喝咖啡的机会,那么您可能想尝试一种动态类型的语言(例如 Smalltalk 或 Clojure) .灵活性很有趣。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-30
    • 1970-01-01
    相关资源
    最近更新 更多