Clojure 是否在惰性序列内部实现惰性序列的差异
我想知道:当您嵌入一个表达式,强制在未实现的外部惰性序列中实现惰性序列时,会发生什么 答:这似乎取决于如何创建外部惰性序列。如果外部序列来自Clojure 是否在惰性序列内部实现惰性序列的差异,clojure,lazy-evaluation,Clojure,Lazy Evaluation,我想知道:当您嵌入一个表达式,强制在未实现的外部惰性序列中实现惰性序列时,会发生什么 答:这似乎取决于如何创建外部惰性序列。如果外部序列来自map,则实现内部序列,如果外部序列来自iterate,则不是 嗯,我很确定这不是描述下面发生的事情的正确方式——我很确定我没有理解一些事情。有人能解释一下吗 (有一个怪癖,map返回一个LazySeq,iterate返回一个Cons围绕LazySeq。因此在下面的类和实现测试中,我看了iterate输出的rest。我不相信和之间的差异e> 映射和迭代与我的
map
,则实现内部序列,如果外部序列来自iterate
,则不是
嗯,我很确定这不是描述下面发生的事情的正确方式——我很确定我没有理解一些事情。有人能解释一下吗
(有一个怪癖,map
返回一个LazySeq
,iterate
返回一个Cons
围绕LazySeq
。因此在下面的类和实现测试中,我看了iterate
输出的rest
。我不相信和之间的差异e> 映射
和迭代
与我的问题有关。)
“当嵌入一个表达式,强制在未实现的外部惰性序列中实现惰性序列时,会发生什么情况?”
如果强制实现内部序列的表达式位于外部序列的未实现部分,则无任何内容
回答:这似乎取决于您如何创建外部惰性序列。如果外部序列来自映射,则内部序列被实现,如果外部序列用于迭代,则不是
不,这只取决于强制表达式是否在未实现部分。无论是map
还是iterate
都不会实现任何尚未实现的内容
“描述下面发生的情况”
你需要仔细考虑这些规则。你的例子的行为主要是渴望与懒惰评估(Clojure是渴望)的结果,并且只与懒惰序列相关
第一个示例
首先考虑表格
(def doa-twice-map (doa-twice three-vec))
第一个元素def
表示一种特殊的形式,带有规则,但特别是当提供第二个参数时,它将被计算。特别是,您正在计算
(doa-twice three-vec)
(doall-once three-vec)
(doall (map print-times-10-ret three-vec))
此表单的评估是在三个vec
上两次调用doa
,如下所示(替换后)
要计算此表单,必须首先计算参数(Clojure进行急切计算)
(doa-twice three-vec)
(doall-once three-vec)
(doall (map print-times-10-ret three-vec))
您的doall once
被参数three-vec
调用。现在您正在计算
(doa-twice three-vec)
(doall-once three-vec)
(doall (map print-times-10-ret three-vec))
这将调用参数上的doall
,该参数首先被计算以创建一个惰性序列。doall
根据定义强制实现该惰性序列。在该实现过程中,您将对三个vec
的连续元素调用print-times-10-ret
,从而强制实现它。
因此,您在这里看到的行为是急切求值链接的结果。急切求值与懒惰求值(Clojure是急切的)不能与懒惰与非懒惰序列混淆(Clojure两者都有)
第二个示例
评估特殊def
表单时
(def doall-once-iter (iterate doall-once three-vec))
这导致对第二个参数进行评估
(iterate doall-once three-vec)
此表单的求值将对其参数调用iterate
。iterate创建一个Cons
-单元格,该单元格由3个vec
和一个惰性序列组成。作为求值结果的Cons
-单元格是一个值,从而结束此处的急切求值链下降。此值设置为def
执行。这是def
表单评估的结束
插入语
(有一个怪癖,当map返回一个LazySeq时,iterate返回一个围绕LazySeq的Cons。因此在下面的类和实现测试中,我查看了iterate的其余输出。我不相信map和iterate之间的差异与我的问题有关。)
正确,这不起作用。如果iterate
返回一个LazySeq
对象,它仍然是一个值,并且如上所述停止计算链的下降
另请参阅如何在不强制实现的情况下计算序列的已实现/非惰性部分。或者,作为对我认为也是你在Clojure Google Group上提出的问题的回答。感谢你提供了如此详细的答案。我不得不通读了几遍,以消除我知道的困惑,但现在我认为关键是p点是:我将函数
doall once
作为参数传递给iterate
,由于iterate
在实现部分序列之前不会调用该函数,因此没有输出。而在doa tweep
的定义中,实际上有一个应用程序doall once
,以及其他的功能事情就是这样发生的。(如果这一切看起来都是正确的,不需要回答。)是的,对了,这就是我在谷歌小组的位置。(顺便说一句,我确实理解了评估,但是,很明显,我对惰性序列的困惑让我失去了理智,我很高兴你了解了细节。)