Reduce和Reduce允许您在序列中累积状态。序列中的每个元素将修改累积状态,直到到达序列的末尾。
在无限列表上调用reduce或reduce意味着什么?
(def c (cycle [0]))
(reduce + c)这将很快抛出一个OutOfMemoryError。顺便说一句,(reduce + (cycle [0]))不会抛出OutOfMemoryError (至少在我等待的时候不会抛出)。它再也不会回来了。不知道为什么。
有没有办法以一种有意义的方式调用无限列表上的reduce或reduce?我在上面的例子中看到的问题是,列表的评估部分最终变得足够大,从而使堆溢出。也许无限列表不是正确的范例。减少生成器、IO流或事件流会更有意义。该值在求值并用于修改状态后不应保留。
发布于 2011-03-08 10:52:43
就目前而言,亚瑟的回答是好的,但他似乎没有回答你关于reductions的第二个问题。如果给定一个只有N个元素的列表,reductions将返回reduce返回的中间阶段的延迟序列。因此,在无限列表上调用reductions是非常明智的:
user=> (take 10 (reductions + (range)))
(0 1 3 6 10 15 21 28 36 45)发布于 2011-03-08 15:51:19
如果你想继续从一个列表中获取项目,比如IO流,并在运行之间保持状态,你不能使用(不使用def),相反,一个好的方法是使用循环/递归,这将允许你避免消耗太多的堆栈空间,并让你保持状态,在你的例子中:
(loop [c (cycle [0])]
(if (evaluate-some-condition (first c))
(do-something-with (first c) (recur (rest c)))
nil))当然,与您的情况相比,这里有一个条件检查,以确保我们不会无限循环。
发布于 2011-03-09 03:12:37
正如其他人所指出的,直接在无限序列上运行reduce是没有意义的,因为reduce是非惰性的,需要消耗完整的序列。
作为这种情况的替代方案,这里有一个有用的函数,它只减少序列中的前n项,使用recur实现,以获得合理的效率:
(defn counted-reduce
([n f s]
(counted-reduce (dec n) f (first s) (rest s) ))
([n f initial s]
(if (<= n 0)
initial
(recur (dec n) f (f initial (first s)) (rest s)))))
(counted-reduce 10000000 + (range))
=> 49999995000000https://stackoverflow.com/questions/5227503
复制相似问题