2024年Clojure状态调查!分享你的想法。

欢迎!请查看关于页面了解如何使用本站。

0
Clojure

以下代码在1.8.0和1.9.0-alpha14版本都无法编译,两个版本都出现了相同的错误。

`
user=> (def fibonacci-1
((fn fib [a b]

(lazy-seq  (cons a  (fib b  (+ a b)))))
0 1))

user=> (filter #(< % 100) fibonacci-1)

ArithmeticException 整数溢出 clojure.lang.Numbers.throwIntOverflow (Numbers.java:1501)

user=> (filter #(< % 100) fibonacci-1)

NullPointerException clojure.lang.Numbers.ops (Numbers.java:1013)

user=> (def fibonacci-2

     (lazy-cat [0 1] (map + (rest fibonacci-2) fibonacci-2)))

user=> (filter #(< % 100) fibonacci-2)

ArithmeticException 整数溢出 clojure.lang.Numbers.throwIntOverflow (Numbers.java:1501)

user=> (filter #(< % 100) fibonacci-2)
(0 1 1 2 3 5 8 13 21 34 55 89)
`

补丁: 0001-CLJ-2069-cache-exceptions-thrown-during-lazy-seq-rea.patch

提案: 缓存在惰性序列实现时抛出的异常,以避免重新运行声明为^:once的主体函数

预审: Alex Miller

共有4个答案

0

评论由:find_my_way

也许我应该使用take-while而不是filter

但是,有人在第一次运行

(filter #(< % 100) fibonacci-2)

时得到ArithmeticException,而第二次运行时得到正确的结果,为什么?

0

评论由:bronsa

空指针异常(NPE)是由于以下因素之间的交互引起的
1. 惰性序列在实现序列的一部分时抛出异常
2. 惰性序列在内部使用^:once清除局部变量

lazy-seq 预期 bodyfn 将会运行一次,并将结果缓存,但如果在执行 bodyfn 期间抛出异常,则在序列尝试第二次实现时该函数将再次运行。然而,如果在 locals 清除已经开始(即使是部分清除),这意味着 bodyfn 中的某些 locals 现在将变为 nil,而不是保持其实际值。

0

评论由:bronsa

附上修复此问题的补丁

0
参考资料:https://clojure.atlassian.net/browse/CLJ-2069(由 alex+import 提出)
...