【发布时间】:2011-11-20 22:09:37
【问题描述】:
为什么 Clojure 的反向函数的设计者认为返回的序列不是惰性序列?
Clojure 通常包含惰性序列。
【问题讨论】:
标签: clojure lisp lazy-evaluation
为什么 Clojure 的反向函数的设计者认为返回的序列不是惰性序列?
Clojure 通常包含惰性序列。
【问题讨论】:
标签: clojure lisp lazy-evaluation
当然是因为根据定义,为了反转一个序列,您必须知道另一端是什么,以便返回将成为反转集合中的第一项的内容。
因此,序列必须是有限的,并且您必须对其进行评估才能使用其末尾的内容。
附录:
反向作为无限序列没有意义,(尽管可以公平地说无限序列并不总是懒惰的先决条件)。
如果您要反转一个集合,那么您已经将它加载到内存中;不需要计算。
【讨论】:
(reduce conj () '(1 2 3)) => (3 2 1)
rseq 返回一个以相反顺序遍历集合的 seq。它仅适用于 可逆 集合,例如矢量、排序集和排序图。
reverse 将反转任何有限序列,但这样做的代价是遍历所有项目并将它们附加到列表中。它被实现为(reduce conj () coll)。这显然不是懒惰的。
【讨论】:
进一步Scott's answer:
reverse 函数逐个元素地减少其序列参数。如果我们可以让reverse 真正变得懒惰,我们可以对其他归约做同样的事情。所以我们写一个懒惰版的reduce:
(defn lazy-reduce [f init coll]
(lazy-seq
(if (seq coll)
(lazy-reduce f (f init (first coll)) (rest coll))
init)))
顺便说一句,这只适用于序列。
但它有效:
(lazy-reduce conj () (range 5))
; (4 3 2 1 0)
如果我们从不接触结果,则不会计算任何内容。我们赢了。但是一旦我们接触到第一个元素,整个序列就实现了,就像用掉线编织一样解开。
【讨论】: