『Programming In Scala』の第23章で、著者は次のような例を示しています。
case class Book(title: String, authors: String*)
val books: List[Book] = // list of books, omitted here
// find all authors who have published at least two books
for (b1 <- books; b2 <- books if b1 != b2;
a1 <- b1.authors; a2 <- b2.authors if a1 == a2)
yield a1
著者によると、これは次のように翻訳されます。
books flatMap (b1 =>
books filter (b2 => b1 != b2) flatMap (b2 =>
b1.authors flatMap (a1 =>
b2.authors filter (a2 => a1 == a2) map (a2 =>
a1))))
しかし、マップとフラットマップのメソッド定義(TraversableLike.scala)を調べると、それらはforループとして定義されていることがわかります。
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
val b = bf(repr)
b.sizeHint(this)
for (x <- this) b += f(x)
b.result
}
def flatMap[B, That](f: A => Traversable[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
val b = bf(repr)
for (x <- this) b ++= f(x)
b.result
}
ええと、これは継続的にforeachに変換されてから、式ではなく構成であるwhileステートメントに変換されると思います。scalaにはfor構成がありません。これは、forが常に何かを生成することを望んでいるためです。
それで、私があなたと話したいのは、なぜScalaがこれを「翻訳のために」行うのかということです。books
著者の例では4つのジェネレーターを使用しましたが、これは最終的に4レベルのネストされたforループに変換されます。これは、が大きい場合に非常に恐ろしいパフォーマンスになると思います。
Scalaは、この種の「シンタックスシュガー」の使用を推奨しています。フィルター、マップ、フラットマップを多用するコードを常に見ることができます。プログラマーは、あるループを別のループの中にネストしていることを忘れているようです。コードを少し短く見せます。あなたの考えは何ですか?