假设我写道:
(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)发布于 2020-05-25 19:36:52
首先,每个延迟的seq只能实现一次。其次,stuff的定义不使用递归-- stuff不是一个函数。如果您查看定义 of lazy-seq,可以看到您对stuff的定义扩展到
(def stuff (new clojure.lang.LazySeq (fn* [] stuff)))当调用到fn构造函数的clojure.lang.LazySeq arg时,它返回已经实现的懒惰seq。因此,当您尝试将延迟的seq打印到REPL时,迭代会立即终止并返回0。
您可以验证stuff的类型是clojure.lang.LazySeq。
user=> (type stuff)
clojure.lang.LazySeq并且,在将stuff打印到REPL之后,实现了stuff。
user=> (realized? stuff)
false
user=> stuff
()
user=> (realized? stuff)
true您可以使用递归来获得您预期的效果。
user=> (defn stuff
[]
(lazy-seq (stuff)))
#'user/stuff
user=> (stuff) ;; Hangs forever.https://stackoverflow.com/questions/62007445
复制相似问题