用于理解和flatMap/map中间结果的Scala

用于理解和flatMap/map中间结果的Scala,scala,for-comprehension,Scala,For Comprehension,从我第一次读到: for { harpo<-list1 if harpo.length>0 groucho<-list2 chico<-list3 } yield (harpo, groucho, chico) 我担心filter,flatMap和map返回的不必要的中间集合。第一个是在Scala 2.8(?)中通过添加with filter方法修复的,我怀疑有一些神奇的东西在改变这些方法的返回类型,这取决于用法,所以当用作flatMap的参数时,它们返回一

从我第一次读到:

for {
  harpo<-list1 if harpo.length>0
  groucho<-list2
  chico<-list3
} yield (harpo, groucho, chico)
我担心
filter
flatMap
map
返回的不必要的中间集合。第一个是在Scala 2.8(?)中通过添加
with filter
方法修复的,我怀疑有一些神奇的东西在改变这些方法的返回类型,这取决于用法,所以当用作
flatMap
的参数时,它们返回一个非严格的集合,但我找不到任何证据。我的怀疑是对的吗?它并不像乍一看那样无效吗?

这与。具体地说,by@IODEV向您展示了如何查看desugared表单:

$ 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)'

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

val b = List.newBuilder[(String, String, String)]
for(harpo <- list1 if harpo.length() > 0; groucho <- list2; chico <- list3) {
  b += ((harpo, groucho, chico))
}
b.result()
val b=List.newBuilder[(字符串,字符串,字符串)]

对于(harpo 0;groucho),也许我应该更清楚一些。我的问题是:在这种情况下,list3.map和list2.flatMap返回的集合是否严格?如果它们严格,则重复构建它们,只是为了在将元素放入父集合后丢弃。如果我只是执行
val l=list3.map(“兄弟”+\ux)在这种情况下,一个典型的C++模式是使用一个懒惰的中间类型,当它被分配给一个预期返回类型的变量时,它会隐式地转换成严格的类型。我不知道Scala中是否有可能,但是它的类型推断仍然有我的秘密。非常严格(您不指定它们的类型,但假设它们属于
List
)因此,内部循环创建了严格的中间结果。我不知道C++集合,但我怀疑您可以以一种懒惰的方式嵌套<代码> FLATMAP,消除任何中间集合-<代码> MAP>代码>和<代码>过滤器<代码>是的,但不是<代码>平面图< /代码>。如果需要,使用Builder和<代码>的迭代方法。正如我所说的,不要被过早的优化所束缚。
list1.withFilter(_.length() > 0)
  .flatMap(harpo =>
    list2.flatMap(groucho =>
      list3.map(chico => (harpo, groucho, chico))
    )
  )
val b = List.newBuilder[(String, String, String)]
for(harpo <- list1 if harpo.length() > 0; groucho <- list2; chico <- list3) {
  b += ((harpo, groucho, chico))
}
b.result()