我正在关注 Clojure 的乐趣,我对这两个陈述感到困惑
(def very-lazy (-> (iterate #(do (print \.) (inc %)) 1) rest rest rest))
(def less-lazy (-> (iterate #(do (print \.) (inc %)) 1) next next next))
因此,输出是
(println (first very-lazy)) ; .4
(println (first less-lazy)) ; 4
这本书继续解释说
Grabbing the first element in a lazy seq built with rest causes a realization as expected. But the same doesn’t happen for a seq built with next because it’s already been previously realized. Using next causes a lazy seq to be one element less lazy, which might not be desired if the cost of realization is expensive.
我迫切的问题是为什么“非常懒惰”有一个额外的点?我的想法是 'print' 会在调用时打印它的参数,不管
next
或 rest
.谢谢
最佳答案
Print 在这两种情况下实际上做了完全相同的事情,它只打印数字。额外的 .
是由列表中的代码打印的,它恰好与 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
然后创建两个相同的列表,分别从
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=>
a-partially-realized
的前三个元素已经被预先计算而
b-more-fully-realized
的前四个元素已被预先计算。当我们读取
a-partially-realized
的第一个元素(原始列表中的第四个)时,它还没有被计算出来,所以我们会看到它正在被计算。esc.core=> (print (first a-partially-realized))
making new element4nil
当我们对
b-more-fully-realised
做同样的事情时,它已经缓存了值,所以我们立即得到结果。esc.core=> (print (first b-more-fully-realized))
4nil
关于clojure rest 和 next 相关,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7970314/