用于推导和 flatMap / 地图中间结果的 Scala

Tur*_*rin 4 scala for-comprehension

从我第一次读到:

for {
  harpo<-list1 if harpo.length>0
  groucho<-list2
  chico<-list3
} yield (harpo, groucho, chico)
Run Code Online (Sandbox Code Playgroud)

翻译成:

list1.filter(_.length>0).flatMap(harpo =>      
      list2.flatMap(groucho=>list3.map((harpo,groucho,_)))
)
Run Code Online (Sandbox Code Playgroud)

我担心filter, flatMap&返回的不必要的中间集合map。第一个是通过添加withFilter方法在 Scala 2.8(?) 中修复的,我怀疑有一些魔法会根据使用情况改变这些方法的返回类型,因此当用作参数时,flatMap它们返回一个非严格集合,但我找不到任何证据。我的怀疑是对的吗,它并不像乍一看那样无效?

0__*_*0__ 5

这与这个问题有关。具体来说,@IODEV的回答向您展示了如何查看脱糖形式:

$ scala -Xprint:typer -e
'val list1 = List("foo", "bar"); val list2 = list1; val list3 = list1;
for (harpo<-list1 if harpo.length>0; groucho <- list2; chico <- list3) 
yield (harpo, groucho, chico)'
Run Code Online (Sandbox Code Playgroud)

(没有换行符)

list1.withFilter(_.length() > 0)
  .flatMap(harpo =>
    list2.flatMap(groucho =>
      list3.map(chico => (harpo, groucho, chico))
    )
  )
Run Code Online (Sandbox Code Playgroud)

我看不到任何可以保存的浪费的中间集合,除非您使用可变构建器和/whileforeach调用来填充该构建器:

val b = List.newBuilder[(String, String, String)]
for(harpo <- list1 if harpo.length() > 0; groucho <- list2; chico <- list3) {
  b += ((harpo, groucho, chico))
}
b.result()
Run Code Online (Sandbox Code Playgroud)

问题是,您的特定代码是否表现出显着的性能问题。例如,您的收藏非常大。如果不是,请使用更惯用的形式 ( for ... yield)。仅for ... {}在您真正从中获得某些东西时才对构建器进行优化。