clojure休息和下一个相关

thl*_*lim 7 clojure lazy-evaluation lazy-sequences

我正在追随Clojure的喜悦,我对这两个陈述感到困惑

(def very-lazy (-> (iterate #(do (print \.) (inc %)) 1) rest rest rest))

(def less-lazy (-> (iterate #(do (print \.) (inc %)) 1) next next next))
Run Code Online (Sandbox Code Playgroud)

因此,产量是

(println (first very-lazy)) ; .4

(println (first less-lazy)) ; 4
Run Code Online (Sandbox Code Playgroud)

这本书继续解释这一点

抓住使用rest构建的lazy seq中的第一个元素会导致实现预期.但是对于使用next构建的seq也不会发生这种情况,因为它之前已经实现过.使用next会导致lazy seq成为一个不太懒的元素,如果实现成本很高,则可能不需要.

我的问题是为什么"非常懒"会有一个额外的点?我的想法是"打印"将打印其参数时,如果不考虑调用nextrest.

谢谢

Art*_*ldt 7

在两种情况下,打印实际上都做了完全相同的事情,它只打印了数字.额外的内容.是由列表中的代码打印出来的,它恰好发生在打印的同时4,因此它最终在屏幕上显示.

额外的点是在运行中创建的延迟序列的副作用.我想提出一个更详细的例子来澄清这个:

从两个相同的列表开始,都是完全懒惰的:

esc.core=> (def a (iterate #(do (print "making new element") (inc %)) 1)) 
#'esc.core/a
esc.core=> (def b (iterate #(do (print "making new element") (inc %)) 1))
#'esc.core/b
Run Code Online (Sandbox Code Playgroud)

然后再制作两个相同的列表,分别从a和的第四个元素开始b

esc.core=> (def a-partially-realized (-> a rest rest rest))
making new elementmaking new element#'esc.core/a-partially-realised
esc.core=> (def b-more-fully-realized (-> b next next next))
making new elementmaking new elementmaking new element#'esc.core/b-more-fully-realised
esc.core=> 
Run Code Online (Sandbox Code Playgroud)

三个元素a-partially-realized已预先计算,
而前四个元素b-more-fully-realized已预先计算.

当我们读取它的第一个元素(原始列表中的第四个)时,a-partially-realized它还没有被计算出来,所以我们将看到它被计算出来.

esc.core=> (print (first a-partially-realized))
making new element4nil
Run Code Online (Sandbox Code Playgroud)

当我们做同样的事情时,b-more-fully-realised它已经有了缓存的值,所以我们立即得到结果.

esc.core=> (print (first b-more-fully-realized))
4nil
Run Code Online (Sandbox Code Playgroud)


Joo*_*aat 5

你错过了一些重要的东西.数点:

user> (def very-lazy (-> (iterate #(do (print \.) (inc %)) 1) rest rest rest))
..#'user/very-lazy

user> (def less-lazy (-> (iterate #(do (print \.) (inc %)) 1) next next next))
...#'user/less-lazy
Run Code Online (Sandbox Code Playgroud)

将代码运行为真实而不仅仅是阅读书籍总是有帮助的.