在“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))))
但是,如果您查看 map 和 flatmap 方法定义(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
}
好吧,我猜这个 for 将不断被翻译成 foreach 然后翻译成 while 语句,这是一个构造而不是表达式,scala 没有 for 构造,因为它希望 for 总是产生一些东西。
那么,我想和你讨论的是,为什么 Scala 会这样做“为了翻译”?作者的例子使用了4个生成器,最后会被翻译成4级嵌套的for循环,我想当它books
很大时它的性能会非常糟糕。
Scala 鼓励人们使用这种“语法糖”,你总是可以看到大量使用 filter、map 和 flatmap 的代码,这似乎程序员忘记了他们真正做的是将一个循环嵌套在另一个循环中,而实现的只是使代码看起来更短。你的想法是什么?