请在 2024 Clojure 状态调查 中分享您的想法!

欢迎!请查看 关于 页面以获取更多关于这个功能的信息。

0
Java 互操作

clojure.core//的一元调用与二进制调用处理0.0作为被除数的方式不同,这可能是由于内联导致的。

(/ 0.0) ;; java.lang.ArithmeticException: Divide by zero (/ 1 0.0) ;;= Infinity (/ 1 (identity 0.0)) ;; java.lang.ArithmeticException: Divide by zero

4 条回答

0

评论者:timmc

相关的代码似乎在 clojure.lang.Numbers/divide 中

if(yops.isZero((Number)y)) throw new ArithmeticException("Divide by zero");

让 Numbers/divide 比 double 运算更严格似乎像是bug;明确地抛出 ArithmeticException 而不是让 JVM 处理,这似乎是做多余的工作。

0

评论者:csm

我认为问题在于 clojure.lang.Numbers 中不同的 divide 变体有不同的语义。Numbers.divide(Object, Object) 执行 isZero 检查,但 Numbers.divide(long, double) 不做(它只是使用 Java 的除法运算符,因为分母是一个值为 0.0 的 double,所以结果为 Infinity)。

类似于 (/ 1 0.0) 的表达式会被编译成调用 Numbers.divide(long, double),因此产生 Infinity。如果第二个参数是函数调用或 var,它看起来像 Object,所以它会被编译成使用 Numbers.divide(Object, Object),此时如果第二个参数为零就会抛出异常(实际上编译成调用 Numbers.divide(long, Object),但是这只是对第一个参数进行装箱并调用另一个变体)。

根据编译时推断的类型对除法有不同的语义似乎是不正确的;然而,我不知道这是否会影响除以零以外的任何除法的实例,因此这可能是非实际的问题。

0
by

评论者:timmc

bq. 我不知道这是否会影响除以零之外的任何除法实例,因此这可能是非实际的问题。

我认为只会在“某些情况下”失败代码更糟糕,因为这样更容易在生产而不是开发中捕捉到错误。

0
by
参考:[https://clojure.atlassian.net/browse/CLJ-1142](https://clojure.atlassian.net/browse/CLJ-1142)(由 timmc 报告)
...