首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无限递归懒惰序列在Clojure中显示为空序列。

无限递归懒惰序列在Clojure中显示为空序列。
EN

Stack Overflow用户
提问于 2020-05-25 17:18:20
回答 1查看 274关注 0票数 3

假设我写道:

代码语言:javascript
复制
(def stuff
  (lazy-seq stuff))

当我在REPL中请求stuff的值时,我希望它会被困在一个无限循环中,因为我将stuff定义为自身(这几乎没有说明这个序列)。

但是,我得到了一个空序列。

代码语言:javascript
复制
> stuff
()

为什么?

编辑:我所说的“递归”是指递归数据,而不是递归函数。

我还是不明白为什么这个序列会终止。作为比较,下面的代码被困在无限循环中(并破坏堆栈)。

代码语言:javascript
复制
(def stuff
  (lazy-seq (cons (first stuff) [])))

一些背景:这个问题源于我试图使用Eratosthenes的筛子来实现一个素数生成器。我的第一次尝试是:

代码语言:javascript
复制
(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会继续要求更多的素数,即使它们还不能计算。所以当它运行得很好的时候,我很惊讶。

代码语言:javascript
复制
> (take 20 primes)
(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71)
EN

回答 1

Stack Overflow用户

发布于 2020-05-25 19:36:52

首先,每个延迟的seq只能实现一次。其次,stuff的定义不使用递归-- stuff不是一个函数。如果您查看定义 of lazy-seq,可以看到您对stuff的定义扩展到

代码语言:javascript
复制
(def stuff (new clojure.lang.LazySeq (fn* [] stuff)))

当调用到fn构造函数的clojure.lang.LazySeq arg时,它返回已经实现的懒惰seq。因此,当您尝试将延迟的seq打印到REPL时,迭代会立即终止并返回0。

您可以验证stuff的类型是clojure.lang.LazySeq

代码语言:javascript
复制
user=> (type stuff)
clojure.lang.LazySeq

并且,在将stuff打印到REPL之后,实现了stuff

代码语言:javascript
复制
user=> (realized? stuff)
false
user=> stuff
()
user=> (realized? stuff)
true

您可以使用递归来获得您预期的效果。

代码语言:javascript
复制
user=> (defn stuff
         []
         (lazy-seq (stuff)))
#'user/stuff
user=> (stuff) ;; Hangs forever.
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62007445

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档