分享您的想法,参加2024 Clojure状态调查!

欢迎!请参阅关于页面,了解更多关于该功能的信息。

0 表达意见
Java互操作

对 clojure.core// 的一元调用与二进制调用对被除数为0.0的情况下处理不同,这可能是由于内联引起的。

(/ 0.0) ;; java.lang.ArithmeticException: 除以零 (/ 1 0.0) ;;= 无穷大 (/ 1 (identity 0.0)) ;; java.lang.ArithmeticException: 除以零

4 答案

0 表达意见

评论者:timo

相关代码看起来像clojure.lang.Numbers/divide中的这个

if(yops.isZero((Number)y)) throw new ArithmeticException("除以零");

让Numbers/divide比双精度运算更严格似乎像是缺陷;明确抛出ArithmeticException而不是让JVM处理,这似乎是工作量不必要的增加。

0 表达意见

评论者:csm

我认为这里的问题是 clojure.lang.Numbers 中不同的除法变体有不同的语义。Numbers.divide(Object, Object) 执行 isZero 检查,但 Numbers.divide(long, double) 不进行(它仅使用Java的除法运算符,由于除数是值为 0.0 的双精度浮点数,因此产生无穷大)。

类似于 (/ 1 0.0) 这样的表达式会被编译成调用 Numbers.divide(long, double),从而产生无穷大。如果第二个参数是一个函数调用或变量,它看起来像是一个对象,因此会编译成使用 Numbers.divide(Object, Object),当第二个参数为零时,这个调用会抛出异常(实际上它编译为对 Numbers.divide(long, Object) 的调用,但这只是将第一个参数装箱并调用其他变体)。

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

0 表达意见

评论者:timo

bq. 我不知道这是否会影响除以零以外的其他除法实例,因此它可能不是一个实际的问题。

我认为只会偶尔失败的字节码更糟糕,因为 bugs 更有可能在生产环境中而不是开发中被发现。

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