Clojure中的lazy-seq有什么作用?

17

我正在查看一些Fibonacci序列Clojure代码的示例:

 (def fibs (lazy-cat [1 2] (map + fibs (rest fibs))))

我大体理解正在发生的事情,但不明白 lazy-cat 的意义。我知道 lazy-cat 是一个宏,将被翻译成类似于这样的东西:


(def fibs (concat (lazy-seq [1 2]) (lazy-seq (map + fibs (rest fibs))))) 

lazy-seq 究竟起到了什么作用?即使没有 lazy-seq,它也仍然会被惰性地评估吗?这仅仅是为了缓存目的吗?

编辑:感谢回答。我困惑的是因为REPL中使用平凡的concat可以正常工作,因为我之前对fibs进行了绑定。

2个回答

16

[1 2]上的lazy-seq并没有必要,但也不会造成影响。

(map + fibs (rest fibs))上的lazy-seq是必需的;如果没有它,函数调用将在将fibs绑定到一个值之前被求值,这将导致异常。通过将其包装在lazy-seq中,调用将被推迟直到需要该值,而此时fibs将有一个值。


7

据我理解(我承认对Clojure还是一个相对新手!),如果你尝试以下操作:

(def fibs (concat [1 2] (map + fibs (rest fibs))))

这段代码不起作用,因为fibs没有绑定,因此后面两个对它的引用都会失败。

然而,您提供的延迟版本将有效,因为只有在序列被消耗时才实际解析对fibs的引用,并且在此之前fibs已成功定义为延迟序列。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接