withFilter而不是filter

Kig*_*gyo 78 scala lazy-evaluation for-comprehension scala-collections

在使用map,flatmap等函数后,使用withFilter而不是过滤器总是更高效吗?

为什么只支持map,flatmap和foreach?(预期的功能如forall/exists)

Sha*_*nds 116

来自Scala文档:

注:之间的区别c filter p,并c withFilter p为前者创造一个新的集合,而后者只限制后续的域map,flatMap,foreach,和withFilter操作.

因此,filter将采用原始集合并生成新集合,但withFilter非严格(即懒惰地)将未经过滤的值传递到以后的map/ flatMap/ withFilter调用,从而节省了第二次通过(已过滤)集合.因此,当传递给这些后续方法调用时,它将更有效.

事实上,它withFilter是专门为处理这些方法的链而设计的,这就是理解被去除的东西.此处不需要其他方法(例如forall/ exists),因此它们尚未添加到FilterMonadic返回类型中withFilter.

  • 仅供参考,我认为[收藏 - 提示和技巧](https://pavelfatin.com/scala-collections-tips-and-tricks/#sequences-rewriting)提供了出色的信息.H5没有锚定,但您可以在链接部分中搜索"不创建临时集合". (5认同)
  • 关于`withFilter`的明确使用,Martin Odersky自己在Coursera的Scala课程中明确地使用了它,我强烈推荐.鉴于他这样做,它也可以让其他人感到安慰,尽管差异通常只有1个字符.例如`seq.view filter p`与`seq withFilter p`. (4认同)

Zen*_*ulz 8

除了Shadowlands的优秀答案之外,我想带一个直观的例子来说明filter和之间的区别withFilter.

我们考虑以下代码

val list = List(1, 2, 3)
var go = true
val result = for(i <- list; if(go)) yield {
   go = false
   i
}
Run Code Online (Sandbox Code Playgroud)

大多数人都希望result等于List(1).自Scala 2.8以来就是这种情况,因为for-comprehension被翻译成了

val result = list withFilter {
  case i => go
} map {
  case i => {
    go = false
    i
  }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,转换将条件转换为调用withFilter.先前的Scala 2.8,for-comprehension被翻译成如下内容:

val r2 = list filter {
  case i => go
} map {
  case i => {
    go = false
    i
  }
}
Run Code Online (Sandbox Code Playgroud)

使用时filter,价值result会大不相同:List(1, 2, 3).我们制作go标志的事实false对过滤器没有影响,因为过滤器已经完成.同样,在Scala 2.8中,使用这个问题解决了这个问题withFilter.当withFilter被使用时,条件被评估每一个元件被一个内部访问的时间map的方法.

参考: - p.120,Scala在行动(涵盖Scala 2.10),Manning出版物,Milanjan Raychaudhuri - Odersky关于理解翻译的想法