6

それはなぜか、

scala> List(1,2,3,4).iterator.map((x: Int) => println(x))

印刷されません

1
2
3
4

その間

List(1,2,3,4).map((x: Int) => println(x))
List(1,2,3,4).foreach((x: Int) => println(x))
List(1,2,3,4).iterator.foreach((x: Int) => println(x))

すべてですか?

言い換えれば、タイプ T を Unit にマップし、副作用を持つイテレーターのマップがそれらの副作用を表示できないのはなぜですか?

編集:

また、イテレーターが遅延している場合、次の lazyMap の呼び出しが実際に新しいイテレーターを最初から最後まで計算する (完全な新しいイテレーターを提供する) のはなぜですか?

def lazyMap[T, U](coll: Iterable[T], f: T => U) = new Iterable[U] {
  def iterator = coll.iterator map f
}

scala> lazyMap(List(1,2,3,4), (x: Int) => x + 1)
res4: java.lang.Object with Iterable[Int] = (2, 3, 4, 5)
4

2 に答える 2

7

イテレータの原因マップは怠惰であり、厳密さが必要です:

scala> List(1,2,3,4).iterator.map((x: Int) => println(x))
res0: Iterator[Unit] = non-empty iterator

// nothing actually happened yet, just remember to do this printing things

scala> res0.toList
1
2
3
4
res1: List[Unit] = List((), (), (), ())

イテレータで foreach を実行すると、副作用が発生していることは明らかであるため、遅延は望ましくありません。マップについてはそうは言いませんでした。

UPD

あなたの編集に関して:このような動作の理由は、ステートメントの結果に対して toString の暗黙的な呼び出しがあり、それがイテレータを厳密にするためです-このコードを自分で試してください:

scala> { lazyMap(List(1,2,3,4), {(x: Int) => println(x); x + 1}); 1 }

f関数が呼び出されないことがわかります

于 2012-09-28T00:03:39.370 に答える
6

Iterator のポイントは怠惰です。つまり、Iterator を作成すると、データを読み取るまで何も評価されません。これは次のようになります。

scala> val itr = List(1,2,3).iterator
itr: Iterator[Int] = non-empty iterator

わかりました、これでイテレータができました。しかし、実際にはまだリストを見ていません。

scala> val mappedItr = itr.map((x: Int) => println(x))
mappedItr: Iterator[Unit] = non-empty iterator

これで、新しい Iterator ができました。これは、データがアクセスされると、マップされた関数を適用します。しかし、まだ元のリストを実際に見ていません。

scala> mappedItr.next
1

データにアクセスしたのはこれが初めてなので、Iterator がリストを調べたのはこれが初めてです。を呼び出しnextたので、最初の要素を取得しました。イテレータはmapキューに入れられているため、その要素にアクセスすると、マップされた関数が適用されます。したがって、nextアイテムに適用された関数の結果が表示されます。

次の要素を取得するためにもう一度実行できます。

scala> mappedItr.next
2

また、最終結果を得るために必要な場合にのみ関数を評価します。

于 2012-09-28T00:03:48.613 に答える