我想知道:当你嵌入一个强制在外部懒惰序列中实现懒惰序列的表达式时,会发生什么?
答案:这似乎取决于你如何创建外部懒惰序列。如果外部序列来自map
,则内部序列被实现,如果外部序列来自iterate
,则它不是。map
。
嗯,我很确定这不是描述下面发生的事情的正确方法 - 我很确定我不理解某些事情。有人可以解释一下吗?
(有一个怪癖,就是当LazySeq
返回iterate
时,Cons
会返回LazySeq
rest
。{下面是对类和实现的测试,我看一下iterate
输出的map
。我不相信iterate
和(def three-vec (range 1 4))
(defn print-times-10-ret [x]
(let [y (* 10 x)]
(println "[" y "] " )
y))
(defn once [xs] (map print-times-10-ret xs))
(defn doall-once [xs] (doall (map print-times-10-ret xs)))
(defn doa-twice [xs] (once (doall-once xs))) ; "doa" since only half doall-ed
;; Here the inner sequence seems to get realized:
(def doa-twice-map (doa-twice three-vec))
; printed output:
; [ 10 ]
; [ 20 ]
; [ 30 ]
;; Here we create a lazy sequence that will call doall-once when
;; realized, but nothing gets realized:
(def doall-once-iter (iterate doall-once three-vec))
; no printed output
(class doa-twice-map)
; => clojure.lang.LazySeq
;; Note that this is not realized, even though the inner seq was realized (?):
(realized? doa-twice-map)
; => false
(class (rest doall-once-iter))
; => clojure.lang.LazySeq
(realized? (rest doall-once-iter))
; => false
之间的这种区别有什么与我的问题有关。)
{{1}}
答案 0 :(得分:7)
如果强制实现内部序列的表达式在外部序列的未实现部分中,那么什么都没有。
不,它只取决于你的强制表达是否在未实现的部分。 map
和iterate
都没有意识到任何尚未实现的内容。
您需要仔细考虑evaluation规则。你的例子的行为主要是渴望与懒惰评价的结果(Clojure非常渴望),并且只与懒惰序列相关。
第一个例子
首先考虑表格
(def doa-twice-map (doa-twice three-vec))
第一个元素def
表示一个特殊形式,带有special evaluation个规则,但特别是当提供第二个参数时,它会被评估。特别是,您正在评估
(doa-twice three-vec)
此表单的评估是doa-twice
three-vec
的调用,如下所示(替换后)
(once (doall-once three-vec)))
要评估此表单,必须首先评估参数(Clojure急切评估)。特别是,您正在评估
(doall-once three-vec)
使用参数doall-once
调用three-vec
。现在你正在评估
(doall (map print-times-10-ret three-vec))
这将在参数上调用doall
,首先对其进行求值以创建延迟序列。根据定义,doall
强制实现该延迟序列。在那个实现过程中,你在print-times-10-ret
的连续元素上调用three-vec
,迫使它一路上实现它。
因此,您在此处看到的行为是热切评估的链接的结果。渴望与懒惰的评价(Clojure非常渴望)不要与懒惰与非懒惰的序列相混淆(Clojure都有)。
第二个例子
评估特殊def
表单
(def doall-once-iter (iterate doall-once three-vec))
这导致评估第二个参数
(iterate doall-once three-vec)
对此表单的评估会在其参数上调用iterate
。 Iterate创建Cons
- three-vec
的单元格和一个惰性序列。作为评估结果的Cons
- 单元格是值,从而结束了此处热切评估的链接下降。此值设置为doall-once-iter
var与def
的根绑定。这是对def
表单的评估结束。
"(有一个怪癖,就是当map返回一个LazySeq时,iterate返回一个围绕LazySeq的Cons。所以在下面的类和实现的测试中,我看看剩下的迭代的输出。我不相信map和iterate之间的区别与我的问题有关。)"
正确,这不起作用。如果iterate
返回LazySeq
个对象,则它仍然是值并停止评估链的下降,如上所述。
另请参阅count-realized,了解如何在不强制实现的情况下计算序列的已实现/非延迟部分。或者,seq-realized?回应我的想法也是您对Clojure Google Group的质疑。