Clojure:减少,减少和无限列表 [英] Clojure: reduce, reductions and infinite lists

查看:132
本文介绍了Clojure:减少,减少和无限列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

减少和减少让您在序列上累积状态。
序列中的每个元素将修改累积状态,直到达到
结束序列。

Reduce and reductions let you accumulate state over a sequence. Each element in the sequence will modify the accumulated state until the end of the sequence is reached.

在无限列表上调用减少或减少的影响是什么?

What are implications of calling reduce or reductions on an infinite list?

(def c (cycle [0]))
(reduce + c)

这将迅速抛出OutOfMemoryError。顺便说一下,(reduce +(cycle [0]))不会抛出OutOfMemoryError(至少不是在我等待的时间)。它永远不会回来。不知道为什么。

This will quickly throw an OutOfMemoryError. By the way, (reduce + (cycle [0])) does not throw an OutOfMemoryError (at least not for the time I waited). It never returns. Not sure why.

有没有办法以一种有意义的方式调用无限列表中的减少或减少?我在上面的例子中看到的问题是,最终列表的求值部分变得足够大,溢出堆。也许一个无限列表不是正确的范式。减少生成器,IO流或事件流会更有意义。该值不应在评估后用于修改状态。

Is there any way to call reduce or reductions on an infinite list in a way that makes sense? The problem I see in the above example, is that eventually the evaluated part of the list becomes large enough to overflow the heap. Maybe an infinite list is not the right paradigm. Reducing over a generator, IO stream, or an event stream would make more sense. The value should not be kept after it's evaluated and used to modify the state.

推荐答案

它将永远不会返回,因为reduce需要一个序列和一个函数,并应用该函数,直到输入序列为空,只有这样才能知道它有最终值。

It will never return because reduce takes a sequence and a function and applies the function until the input sequence is empty, only then can it know it has the final value.

减少一个真正的无限seq不会有很大的意义,除非它产生一个效果就像记录它的进度。

Reduce on a truly infinite seq would not make a lot of sense unless it is producing a side effect like logging its progress.

在第一个示例中,您首先创建一个引用无限序列的var。

In your first example you are first creating a var referencing an infinite sequence.

(def c (cycle [0]))

var c减少它开始读取元素以更新其状态。

Then you are passing the contents of the var c to reduce which starts reading elements to update its state.

(reduce + c)

这些元素不能被垃圾回收,因为var c持有对第一个元素的引用,而后者持有对第二个的引用,等等。最后,它读取多少,因为堆中有空间然后OOM。

These elements can't be garbage collected because the var c holds a reference to the first of them, which in turn holds a reference to the second and so on. Eventually it reads as many as there is space in the heap and then OOM.

为了防止吹你的第二个例子你不保留对数据的引用您已经使用,所以循环返回的seq上的项目是GCd的速度,因为他们是生产和累积的结果继续变大。最终,它会溢出一个很长的时间,崩溃(clojure 1.3)或促进自己的BigInteger,并增长到所有的堆大小(clojure 1.2)

To keep from blowing the heap in your second example you are not keeping a reference to the data you have already used so the items on the seq returned by cycle are GCd as fast as they are produced and the accumulated result continues to get bigger. Eventually it would overflow a long and crash (clojure 1.3) or promote itself to a BigInteger and grow to the size of all the heap (clojure 1.2)

(reduce + (cycle [0]))

这篇关于Clojure:减少,减少和无限列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆