【发布时间】:2019-04-14 20:50:08
【问题描述】:
我目前正在 Clojure 中为 Project Euler 问题之一实施解决方案,即埃拉托色尼筛 (https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes)。这是我的代码:
(defn cross-first-element [coll]
(filter #(not (zero? (rem % (first coll)))) coll))
(println
(last
(map first
(take-while
(fn [[primes sieve]] (not (empty? sieve)))
(iterate
(fn [[primes sieve]] [(conj primes (first sieve)) (cross-first-element sieve)])
[[] (range 2 2000001)])))))
基本思想是有两个集合 - 已经从筛子中检索到的素数,以及剩余的筛子本身。我们从空的primes 开始,直到筛子为空,我们选择它的第一个元素并将其附加到primes,然后我们从筛子中划掉它的倍数。当它用尽时,我们知道我们所有的质数都在 200 万以下。
不幸的是,尽管它适用于筛子的小上限(比如 1000),但它会导致 java.lang.StackOverflowError 具有长堆栈跟踪,重复序列为:
...
clojure.lang.RT.seq (RT.java:531)
clojure.core$seq__5387.invokeStatic (core.clj:137)
clojure.core$filter$fn__5878.invoke (core.clj:2809)
clojure.lang.LazySeq.sval (LazySeq.java:42)
clojure.lang.LazySeq.seq (LazySeq.java:51)
...
我的解决方案中的概念错误在哪里?如何解决?
【问题讨论】:
-
请注意,您可能需要查看
->>。这将使这段代码更干净:gist.github.com/carcigenicate/ec7147870b2398aa2ca598f5effdd74b -
@Carcigenicate 感谢您指出这一点,我已经学习 Clojure 一个星期了,我还有很多东西要学:)
-
几乎是一个 exact 的骗子 (stackoverflow.com/questions/29073273/…),虽然我不确定修复是否适用于此。
-
已经有一段时间了,但我发现了一篇有趣的文章,专门针对函数式编程的上下文中的这个数学问题 :) 也许它也可以帮助其他人理解为什么这种方法是错误的并且效率如此之低:article
标签: clojure stack-overflow lazy-evaluation