【发布时间】:2020-05-25 17:18:20
【问题描述】:
假设我写了:
(def stuff
(lazy-seq stuff))
当我在 REPL 中询问 stuff 的值时,我希望它会陷入无限循环,因为我将 stuff 定义为它本身(这几乎没有说明这个序列) .
但是,我得到了一个空序列。
> stuff
()
为什么?
编辑:“递归”是指递归数据,而不是递归函数。
我仍然对序列终止的原因感到困惑。作为对比,下面的代码陷入了无限循环(并且炸毁了堆栈)。
(def stuff
(lazy-seq (cons (first stuff) [])))
一些背景:这个问题源于我试图使用 Eratosthenes 的筛子来实现一个素数生成器。我的第一次尝试是:
(def primes
(lazy-seq (cons 2
(remove (fn [x]
(let [ps (take-while #(< % x) primes)]
(some #(zero? (mod x %)) ps)))
(range 3 inf))))) ;; My customized range function that returns an infinite sequence
我认为它永远不会起作用,因为take-while 会继续要求更多的素数,即使它们还无法计算。所以当它工作得很好时,我感到很惊讶。
> (take 20 primes)
(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71)
【问题讨论】:
-
您需要更具体。您可能希望阅读这些文档资源,尤其是 Getting Clojure 和 Brave Clojure:github.com/io-tupelo/clj-template#documentation
-
它不能产生无限循环,因为那里没有函数调用。正如预期的那样会产生无限循环的是
(defn stuff [] (lazy-seq (stuff))) -
@leetwinski 可以产生一个只有惰性序列的无限循环。查看我的编辑。
-
take-while受 x 的限制,并且 x 是当前素数“上限”,因此它永远不会要求比已经生成的素数更多的素数。另外range已经产生了无限序列,无需自定义。(drop 3 (range)),或(iterate inc 3) -
@YizheSun 我研究了为什么@leetwinski 对
primes的定义有效,并在一篇博文中写道:phillippe.siclait.com/blog/primes-lazy-sequence
标签: clojure