2

(line <-lines)がと​​ても壊滅的であることに私は非常に驚きました!ラインイテレータを完全に巻き戻します。したがって、次のスニペットを実行すると、サイズ=0になります。

  val lines = Source.fromFile(args(0)).getLines()
  var cnt = 0
  for (line <- lines) {
    cnt = readLines(line, cnt)
  }
  val size = lines.size

このようなよく隠された副作用があるのは通常のScalaの習慣ですか?

4

2 に答える 2

5

Source.getLines()イテレータを返します。すべてのイテレータについて、上記のような一括操作、foreachまたはmap、、などを呼び出すと、イテレータは使用可能な状態ではなくなります。これは、 sのコントラクトであり、より一般的には、を継承するクラスです。taketoListIteratorTraversableOnce

特に明記されていない限り、メソッドを呼び出した後はイテレータを使用しないでください。最も重要な2つの例外は、nextとhasNextの唯一の抽象メソッドでもあります。

これは、継承するクラスには当てはまりません。クラスの場合Traversable、バルクトラバーサル操作を何度でも呼び出すことができます。

于 2013-03-19T14:55:47.917 に答える
3

Source.getLines()を返しIterator、を歩くとIteratorそれが変化します。これはScalaのドキュメントで非常に明確にされています

イテレータは変更可能です。イテレータに対するほとんどの操作は、その状態を変更します。コレクションの要素を反復処理するためによく使用されますが、コレクションに支えられずに使用することもできます(コンパニオンオブジェクトのコンストラクターを参照)。

特に明記されていない限り、メソッドを呼び出した後はイテレータを使用しないでください。最も重要な2つの例外は、nextとhasNextの唯一の抽象メソッドでもあります。

表記法を使用することは、イテレータforを呼び出すための単なる構文糖衣であり、イテレータを使用しないことを示す非常に明確なドキュメントがあります。mapflatMapforeach

再利用:このメソッドを呼び出した後、呼び出されたイテレータを破棄し、返されたイテレータのみを使用する必要があります。古いイテレータの使用は未定義であり、変更される可能性があり、新しいイテレータも変更される可能性があります。

Scalaは一般的に「実用的な」言語を目指しています。ミューテーションと副作用は、パフォーマンスと相互運用性の理由から許可されていますが、推奨されていません。しかし、それを「よく隠された」と呼ぶのは、ちょっとしたことです。

于 2013-03-19T14:56:11.767 に答える