How lazy sequence run in this code
代码在这里:
1 | (def fib-seq (lazy-cat [0 1] (map + (rest fib-seq) fib-seq ))) |
据我了解,
通过查看
但是我无法弄清楚在需要时如何生成惰性序列,因此我对其添加了一些副作用。
1 2 3 | (def fib-seq (lazy-cat [0 1] (map + (do (println"R") (rest fib-seq)) (do (println"B") fib-seq)))) |
通过添加
1 2 3 4 | user=> (take 5 fib-seq) ; this is the first time I take 5 elements (0 R B 1 1 2 3) |
上面的输出看起来已经很奇怪了,因为它没有逐元素打印R和B,但是让我们看一下下一步。
第一次获取元素后:
1 2 | user=> (take 20 fib-seq) (0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181) |
我再也不会收到
有什么可以向我逐步解释吗?
顺便说一句,是否有可能像
好的,一步一步来:
这是
1 2 3 4 5 6 7 8 9 | (defmacro lazy-cat "Expands to code which yields a lazy sequence of the concatenation of the supplied colls. Each coll expr is not evaluated until it is needed. (lazy-cat xs ys zs) === (concat (lazy-seq xs) (lazy-seq ys) (lazy-seq zs))" {:added"1.0"} [& colls] `(concat ~@(map #(list `lazy-seq %) colls))) |
所以你的代码:
1 2 3 | (def fib-seq (lazy-cat [0 1] (map + (do (println"R") (rest fib-seq)) (do (println"B") fib-seq)))) |
扩展为:
1 2 3 4 | (def fib-seq (concat (lazy-seq [0 1]) (lazy-seq (map + (do (println"R") (rest fib-seq)) (do (println"B") fib-seq))))) |
第一次遍历
1 2 3 4 | (concat (lazy-seq [0 1]) (lazy-seq (map + (do (println"R") (rest fib-seq)) (do (println"B") fib-seq)))) |
在这里,
因此
对于下一个元素,
在
要在每次从
1 2 3 4 5 | (def fib-seq (lazy-cat [0 1] (map + (map #(do (println"R") %) (rest fib-seq)) (map #(do (println"B") %) fib-seq))))) |
感谢@omiel提供了许多有用的信息,但是仍然没有碰到最敏感的地方,经过一会儿的思考,我弄清楚了在生成惰性序列时发生了什么。
如果我确实错了,可以在
我的意思是逐步一步一步地专注于延迟序列项的生成,我已经知道了clojure语言的一些逻辑。
我们知道
虽然很容易理解访问前两项只是意味着要触摸这两件事,并且它们在内存中或已缓存,所以可以直接将它们返回并打印出来。
由于
由于
在这里,调用
通过简单地用list替换变量名,map的代码如下所示:
1 | (map + (rest [0 1 ..]) [0 1 ..] ); the '..' means it is a lazy sequence |
然后执行
1 2 3 4 5 6 | (map + [1 ..] [0 1 ..] ) ^ ^ | ----- | | + 1 |
当
然后
1 | [0 1 1 ..] |
非常好。现在,让我们触摸
fib-seq发现它不包含索引为
现在线程移到
地图发现它没有2号物品,因此必须生成它。并将
1 | (map + (rest [0 1 1..]) [0 1 1..] ) |
然后,当然
1 | (map + [1 1..] [0 1 1..] ) |
我认为,这里最棘手的事情发生了。
1 2 3 4 5 6 | (map + [1 1..] [0 1 1..] ) ^ ^ | ----- | | + 2 |
因此,地图可以将
对于此
1 2 | 0 1 1 2 3 5 .. 1 1 2 3 5 .. |
当然,哪一种是生成
摘要
总而言之,从人类的角度来看,惰性序列会始终从其最后一个状态/位置生成项目,而不是从其初始状态开始生成项目。
如果我错了,请指正我,我是
BTW
我想为