15

Python では、次のようなことができます。

lazy = ((i,j) for i in range(0,10000) for j in range(0,10000))
sum((1 for i in lazy))

しばらく時間がかかりますが、メモリ使用量は一定です。

scala での同じ構造:

(for(i<-0 to 10000; j<-i+1 to 10000) yield (i,j)).count((a:(Int,Int)) => true)

しばらくすると、java.lang.OutOfMemoryError遅延評価する必要があるにもかかわらず、 が表示されます。

4

2 に答える 2

25

Scala の for-comprehension について、本質的に怠け者というものはありません。これは、2 つの範囲の組み合わせが熱心になるという事実を変えない構文糖衣*です。

範囲の遅延viewを使用すると、理解の結果も遅延になります。

scala> for(i<-(0 to 10000).view; j<-(i+1 to 10000).view) yield (i,j)
res0: scala.collection.SeqView[(Int, Int),Seq[_]] = SeqViewN(...)

scala> res0.count((a: (Int, Int)) => true)
res1: Int = 50005000

ここでの怠惰は for 内包表記とは関係ありませんが、flatMapor map(以下を参照) が何らかのタイプのコンテナーで呼び出されると、同じタイプのコンテナーで結果が返されるためです。したがって、for-comprehension は、入力したものの怠惰 (または欠如) を保持するだけです。


*次のような場合:

(0 to 10000).flatMap(i => (i+1 to 10000).map(j => (i, j)))
于 2011-08-09T12:25:55.037 に答える
13

怠惰は理解のためではなく、コレクション自体から来ます。コレクションの厳密さの特徴を調べる必要があります。

しかし、怠惰な :-) のために、ここに要約を示します:Iteratorおよびは、任意のコレクションStreamの選択されたメソッドと同様に、厳格ではありません。viewしたがって、怠惰が必要な場合は、必ず.iterator.viewまたは.toStreamコレクションを最初に実行してください。

于 2011-08-09T12:43:03.113 に答える