【发布时间】:2014-11-03 12:08:19
【问题描述】:
在 Scala 集合中,如果想要遍历集合(不返回结果,即对集合的每个元素产生副作用),可以使用
final def foreach(f: (A) ⇒ Unit): Unit
或
final def map[B](f: (A) ⇒ B): SomeCollectionClass[B]
除了可能的惰性映射 (*) 之外,从最终用户的角度来看,我发现这些调用的差异为零:
myCollection.foreach { element =>
doStuffWithElement(element);
}
myCollection.map { element =>
doStuffWithElement(element);
}
鉴于我可以忽略地图输出的内容。当map 似乎包含foreach 的所有功能时,我想不出应该存在和使用两种不同方法的任何具体原因,事实上,如果一个智能编译器& VM 不会优化该集合对象的创建,因为它没有分配给任何东西,也没有在任何地方读取或使用。
所以,问题是 - 我是对的 - 没有理由在代码中的任何地方调用 foreach?
注意事项:
(*) 惰性映射概念as throughly illustrated in this question 可能会改变一些事情并证明foreach 的使用是合理的,但据我所知,特别需要偶然发现LazyMap,正常
(**) 如果一个人不是使用一个集合,而是编写一个集合,那么人们很快就会发现for 理解语法实际上是一个事实生成“foreach”调用的语法糖,即这两行生成完全等效的代码:
for (element <- myCollection) { doStuffWithElement(element); }
myCollection.foreach { element => doStuffWithElement(element); }
因此,如果有人关心其他人使用具有for 语法的集合类,则可能仍希望实现foreach 方法。
【问题讨论】:
-
最好使用
foreach而不是map来区分副作用和非副作用功能。我不在乎编译器是否为另一个优化了一个。差异使代码的目的更加明显。 -
为了比 LimbSoup 更进一步,我更喜欢直接使用
for ..(无产量)而不是.foreach,因为它进一步(对我而言)显示了迭代之间的鸿沟for 副作用和序列转换。此外,假设被迭代的序列不是惰性的可能很危险。 -
与你相反,如果当前的 Scala 编译器和/或 JVM 能够将
map优化为foreach代码,我会印象深刻结果未使用。在我看来,这是一个非常非常重要的优化。
标签: scala foreach scala-collections side-effects