Scala: "map"vs "foreach"- 在实践中是否有任何理由使用 "foreach"?

标签 scala foreach scala-collections side-effects

在 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 输出的内容。当map 时,我想不出应该存在和使用两种不同方法的任何具体原因。似乎包含了 foreach 的所有功能,事实上,如果智能编译器和虚拟机不会优化集合对象的创建,因为它没有分配给任何东西,或者在任何地方读取或使用,我会印象深刻。

所以,问题是——我说得对吗——没有理由调用 foreach代码中的任何地方?

备注:

(*) 惰性映射概念,as throughly illustrated in this question , 可能会改变一些事情并证明 foreach 的使用是合理的,但据我所知,特别需要偶然发现 LazyMap , 普通的

(**) 如果一个人不是在使用集合,而是在编写一个集合,那么很快就会发现 for理解语法语法实际上是生成“foreach”调用的语法糖,即这两行生成完全等效的代码:
for (element <- myCollection) { doStuffWithElement(element); }
myCollection.foreach { element => doStuffWithElement(element); }

因此,如果有人关心其他人使用带有 for 的集合类语法,可能仍想实现 foreach方法。

最佳答案

我能想到几个动机:

  • foreach是类型为 Unit 的方法的最后一行您的编译器不会发出警告,但会发出 map (并且您需要 -Ywarn-value-discard 开启)。有时你会得到 warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses使用 map但不会使用 foreach .
  • 一般可读性 - 读者可以一眼就知道你改变了一些状态而不返回一些东西,但是如果 map 则需要更多的认知资源来理解相同的操作被使用
  • 除了 1. 你还可以在传递命名函数时进行类型检查,然后进入 mapforeach
  • 使用 foreach不会建立一个新列表,所以效率会更高(感谢@Vishnu)
  • 关于Scala: "map"vs "foreach"- 在实践中是否有任何理由使用 "foreach"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25755312/

    相关文章:

    angular - _.forEach 循环值改变所有继承的数据

    scala - Scala 中的垂直直方图

    scala - Scala 中的树集合

    java - 使用 java -jar 运行 scala 应用程序

    scala - EitherT 没有正确向上转换为共同特征父类(super class)型 (Scala 3)

    javascript - 嵌套 forEach 循环中的异步代码 - React Native

    javascript - 如何增加foreach Angular 值?

    scala - Scala 中的自定义控制结构?

    scala - 使用 Mockito 模拟 Scala void 函数

    scala - 添加两个 Set[Any]