Functional programming 取决于先前元素的延迟序列
学习clojure,尝试创建所有素数的惰性无限序列。 我知道有更有效的算法;我做以下工作更多的是作为一个POC/课程,而不是作为一个理想的解决方案 我有一个函数,给定一系列素数,它告诉我下一个素数是什么:Functional programming 取决于先前元素的延迟序列,functional-programming,clojure,Functional Programming,Clojure,学习clojure,尝试创建所有素数的惰性无限序列。 我知道有更有效的算法;我做以下工作更多的是作为一个POC/课程,而不是作为一个理想的解决方案 我有一个函数,给定一系列素数,它告诉我下一个素数是什么: (next-prime [2 3 5]) ; result: 7 因此,我的惰性序列必须将自身传递给该函数,然后获取结果并将其添加到自身 我的第一次尝试: (def lazy-primes (lazy-cat [2 3 5] (find-next-prime lazy-primes)))
(next-prime [2 3 5]) ; result: 7
因此,我的惰性序列必须将自身传递给该函数,然后获取结果并将其添加到自身
我的第一次尝试:
(def lazy-primes
(lazy-cat [2 3 5] (find-next-prime lazy-primes)))
…这会导致IllegalArgumentException:不知道如何从以下内容创建ISeq:java.lang.Integer
我的第二次尝试:
(def lazy-primes
(lazy-cat [2 3 5] [(find-next-prime lazy-primes)]))
…当我问到10个元素时,这给了我[2 3 5 7]
尝试3:
(def lazy-primes
(lazy-cat [2 3 5]
(conj lazy-primes (find-next-prime lazy-primes))))
(take 10 lazy-primes) ; result: (2 3 5 7 2 3 5 7 2 3)
所有这些似乎都应该起作用(或者至少应该起作用,因为前面的方法不起作用)。为什么我会得到每个案例的假输出?您要寻找的组合是
concat
+lazy seq
+local fn
请看一下在Clojure Contrib库中实现Erathostenes'Sieve:
不过,还有一句话:这个实现使用了一个更简单的方法
Clojure的另一个实现可以在中找到。但是,我不喜欢那个,因为它使用原子,而在Clojure中解决这个算法不需要原子。您最初的尝试不起作用的原因:
(defn seq-fn [builder-fn num ss]
(cons
(builder-fn (take num ss))
(lazy-seq (seq-fn builder-fn (inc num) ss))))
(def lazy-primes
(lazy-cat [2 3 5] (seq-fn next-prime 3 lazy-primes)))
有点复杂,但基本上我所做的是使用高阶helper函数在一组参数上提供闭包,这些参数包括到目前为止创建的素数,以便它可以在每一步递增地生成下一个素数
p、 我相信你们都知道,有更快的算法来生成素数!我假设这主要是为了练习Clojure和使用惰性序列,在这种情况下一切都很好!但是如果你真的关心生成大量的素数,我建议你看看或者,你可以使用iterate:一个内置函数,它惰性地获取一个函数的输出并再次应用到该函数
clojure.core/iterate
([f x])
Returns a lazy sequence of x, (f x), (f (f x)) etc.
f must be free of side-effects
为了让它工作,下一个素数函数应该将其结果连接到其输入,并返回连接
然后您只需调用(take100(iterate list primes[1])就可以得到前100个元素的列表
素数。使用
下一个素数
函数,您可以使用以下代码片段生成所有素数的惰性序列:
(def primes (map peek (iterate #(conj % (next-prime %)) [2])))
有趣的网站,但你能给我解释一下我的代码在做什么吗?