В книге «Программирование на 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), вы можете обнаружить, что они определены как для циклов:
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
}
Что ж, я предполагаю, что это for будет постоянно переводиться в foreach, а затем переводиться в оператор while, который является конструкцией, а не выражением, в scala нет конструкции for, потому что он хочет, чтобы for всегда что-то давал.
Итак, я хочу обсудить с вами, почему Scala делает это «для перевода»? В авторском примере использовалось 4 генератора, которые в итоге будут переведены в 4-уровневый вложенный цикл for. Я думаю, что у него будет действительно ужасная производительность, когда books
большой.
Scala побуждает людей использовать этот вид «синтаксического сахара», вы всегда можете увидеть коды, которые в значительной степени используют фильтры, карты и плоские карты, что, кажется, программисты забывают, что они на самом деле делают, это встраивают один цикл в другой, и то, что достигается, остается только чтобы коды выглядели немного короче. какая у тебя идея?
foreach
петли. Этого и следовало ожидать, поскольку это единственный метод, который кому-то нужно реализовать наTraversable
. - person Daniel C. Sobral   schedule 19.11.2010