Mar*_*ars 3 clojure lazy-evaluation
我想知道:当你嵌入一个表达式来强制实现一个未实现的外部懒惰序列中的惰性序列时会发生什么?
答:这似乎取决于你如何创建外部懒惰序列.如果外部序列来自map,则实现内部序列,如果外部序列出现iterate,则不是.
好吧,我很确定这不是描述下面发生的事情的正确方法 - 我很确定我不理解某些东西.谁能解释一下?
(有一个怪癖,就是在map返回a时LazySeq,iterate返回一个Cons包裹着a 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
Run Code Online (Sandbox Code Playgroud)
如果强制实现内部序列的表达式在外部序列的未实现部分中,那么什么也没有.
不,它只取决于你的强制表达是否在未实现的部分.既没有map也没有iterate意识到任何尚未实现的东西.
您需要仔细考虑评估规则.你的例子的行为主要是渴望与懒惰评价(Clojure渴望)的结果,并且只与懒惰序列切向相关.
第一个例子
首先考虑表格
(def doa-twice-map (doa-twice three-vec))
Run Code Online (Sandbox Code Playgroud)
第一个元素def表示一种特殊形式,具有特殊的评估规则,但特别是当提供第二个参数时,它将被评估.特别是,您正在评估
(doa-twice three-vec)
Run Code Online (Sandbox Code Playgroud)
对此表单的评估是doa-twiceon 的调用,three-vec如下所示(替换后)
(once (doall-once three-vec)))
Run Code Online (Sandbox Code Playgroud)
要评估此形式,必须首先评估参数(Clojure急切评估).特别是,您正在评估
(doall-once three-vec)
Run Code Online (Sandbox Code Playgroud)
而且你的doall-once参数被调用了three-vec.现在你正在评估
(doall (map print-times-10-ret three-vec))
Run Code Online (Sandbox Code Playgroud)
这将调用doall参数,该参数首先被计算以创建一个惰性序列.根据doall定义,力量实现了懒惰序列.在那个实现过程中,你正在调用print-times-10-ret连续的元素three-vec,并在此过程中强制实现它.
因此,您在这里看到的行为是热切评估的链接的结果.渴望与懒惰的评价(Clojure非常渴望)不要与懒惰与非懒惰的序列相混淆(Clojure有两者).
第二个例子
当您评估特殊def表格时
(def doall-once-iter (iterate doall-once three-vec))
Run Code Online (Sandbox Code Playgroud)
这导致第二个参数的评估
(iterate doall-once three-vec)
Run Code Online (Sandbox Code Playgroud)
对此表单的评估会引用iterate其论点.迭代创建Cons的胰岛β细胞three-vec和一个懒惰的序列.这Consβ细胞是评价的结果是一个值,从而结束急于评价的链接这里的血统.此值设置为doall-once-itervar的根绑定def.这是def表格评估的结束.
"(有一个怪癖,就是当map返回一个LazySeq时,iterate返回一个围绕LazySeq的Cons.所以在下面的类和实现的测试中,我看看iterate输出的其余部分.我不知道相信map和iterate之间的区别与我的问题有关.)"
正确,这不起作用.如果iterate返回一个LazySeq对象,它仍然是一个值并停止评估链的下降,如上所述.
另请参阅count-realize,了解如何在不强制实现的情况下计算序列的已实现/非延迟部分.或者,seq-realize?回应我的想法也是你对Clojure Google Group的质疑.