すべての値を評価せずに、yieldをイテレータとして使用することは可能ですか?
Iterator
複雑なリスト生成を実装するのが簡単で、結果を必要としないため、それをに変換する必要がある場合、これは一般的なタスクです...
すべての値を評価せずに、yieldをイテレータとして使用することは可能ですか?
Iterator
複雑なリスト生成を実装するのが簡単で、結果を必要としないため、それをに変換する必要がある場合、これは一般的なタスクです...
もちろん。実際、非厳密性には3つのオプションがあり、以下にリストします。例として、次のことを想定します。
val list = List.range(1, 10)
def compute(n: Int) = {
println("Computing "+n)
n * 2
}
Stream
。AStream
は遅延評価されたリストです。オンデマンドで値を計算しますが、一度計算されると値を再計算しません。ストリームの一部を何度も再利用する場合に最も役立ちます。たとえば、以下のコードを実行すると、「Computing 1」、「Computing 2」、「Computing3」がそれぞれ1回ずつ出力されます。
val stream = for (n <- list.toStream) yield compute(n)
val third = stream(2)
println("%d %d" format (third, stream(2)))
ビュー。_ ビューは、基本コレクションに対する操作の組み合わせです。ビューを調べるとき、調べられる各要素はオンデマンドで計算されます。ビューにランダムにアクセスする場合に最も役立ちますが、ビューのごく一部を見るだけです。たとえば、以下のコードを実行すると、「Computing 3」が2回出力され、それ以外は何も出力されません(結果以外は)。
val view = for (n <- list.view) yield compute(n)
val third = view(2)
println("%d %d" format (third, view(2)))
Iterator
。AnIterator
は、コレクションをゆっくりと歩くために使用されるものです。いわば「ワンショット」コレクションと考えることができます。要素を再計算したり保存したりすることはありません。要素が「計算」されると、再度使用することはできません。そのため、使用するのは少し難しいですが、これらの制約を考慮すると、最も効率的な方法です。たとえば、次の例は、Iterator
インデックス付きアクセスをサポートしていないため(このように記述した場合、ビューのパフォーマンスが低下するため)、異なる必要があります。以下のコードは、「Computing 1」、「Computing 2」、「Computing 3」、「コンピューティング4」、「コンピューティング5」、「コンピューティング6」。また、最後に2つの異なる数値を出力します。
val iterator = for (n <- list.iterator) yield compute(n)
val third = iterator.drop(2).next
println("%d %d" format (third, iterator.drop(2).next))
遅延評価が必要な場合は、ビューを使用してください。ビューを参照してください。
Scalaコレクションを頻繁に使用する場合、 Scala2.8コレクションAPIは素晴らしい読み物です。
私はList
...
scala> List(1, 2, 3)
res0: List[Int] = List(1, 2, 3)
そして関数..。
scala> def foo(i : Int) : String = { println("Eval: " + i); i.toString + "Foo" }
foo: (i: Int)String
そして今、私は理解のためにIterator
...
scala> for { i <- res0.iterator } yield foo(i)
res2: Iterator[java.lang.String] = non-empty iterator
flatMap
、map
およびfilter
メソッドを使用すると、任意のタイプの理解にforを使用できます。ビューを使用することもできます:
scala> for { i <- res0.view } yield foo(i)
res3: scala.collection.SeqView[String,Seq[_]] = SeqViewM(...)
どちらの場合も評価は厳密ではありません...
scala> res3.head
Eval: 1
res4: String = 1Foo