Scala:"map"vs"foreach" - 有没有理由在实践中使用"foreach"?

Gre*_*Cat 14 foreach scala side-effects scala-collections

在Scala集合中,如果想要迭代集合(不返回结果,即对集合的每个元素执行副作用),则可以使用

final def foreach(f: (A) ? Unit): Unit
Run Code Online (Sandbox Code Playgroud)

要么

final def map[B](f: (A) ? B): SomeCollectionClass[B]
Run Code Online (Sandbox Code Playgroud)

除了可能的延迟映射(*)之外,从最终用户的角度来看,我发现这些调用没有差异:

myCollection.foreach { element =>
  doStuffWithElement(element);
}

myCollection.map { element =>
  doStuffWithElement(element);
}
Run Code Online (Sandbox Code Playgroud)

鉴于我可以忽略哪些地图输出.我想不出为什么两种不同的方法应该存在和使用的任何具体原因,当时map似乎包含了所有的功能foreach,事实上,如果智能编译器和VM不会优化,我会非常感动由于它没有分配给任何东西,或者在任何地方读取或使用,因此创建了该集合对象.

所以,问题是 - 我是对的 - 并且没有理由foreach在一个人的代码中调用任何地方?

笔记:

(*)如本问题中所说明的那样,懒惰的映射概念可能会改变一些事情并证明其使用的合理性foreach,但据我所知,一个人特别需要偶然发现LazyMap,正常

(**)如果一个人没有使用集合,而是一个集合,那么很快就会发现for理解语法语法实际上是生成"foreach"调用的语法糖这一事实,即这两行生成完全等效的代码:

for (element <- myCollection) { doStuffWithElement(element); }
myCollection.foreach { element => doStuffWithElement(element); }
Run Code Online (Sandbox Code Playgroud)

因此,如果一个人关心使用该for语法的集合类的其他人,可能仍然想要实现foreach方法.

sam*_*est 13

我可以想到几个动机:

  1. 如果foreach是类型为方法的方法的最后一行,则Unit编译器不会发出警告但会显示map(并且您需要-Ywarn-value-discard启用).有时你会warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses使用,map但不会foreach.
  2. 一般的可读性 - 读者可以知道你在不改变某些状态的情况下改变一些状态,但是如果map使用的话,需要更多的认知资源来理解相同的操作
  3. 继续到1.你还可以在传递命名函数时进行类型检查,然后进入mapforeach
  4. 使用foreach不会构建新的列表,因此会更有效(感谢@Vishnu)


Chr*_*tin 6

scala> (1 to 5).iterator map println
res0: Iterator[Unit] = non-empty iterator

scala> (1 to 5).iterator foreach println
1
2
3
4
5
Run Code Online (Sandbox Code Playgroud)