为什么在Scala中使用foreach比get更好呢?

48

为什么在 Scala 的 Options 中,使用 foreachmapflatMap 等方法比使用 get 更好?如果我使用 isEmpty,那么调用get 是安全的。

6个回答

85

这有点涉及到"讲述,而不是询问"。考虑以下两行代码:

if (opt.isDefined) println(opt.get)
// versus
opt foreach println
在第一种情况下,你正在查看opt中的内容,然后根据所看到的做出反应。而在第二种情况下,你只是告诉opt你想要做什么,然后让它去处理。
第一种情况过于熟悉Option,复制了内部逻辑,很容易出错(如果编写不正确,可能会导致运行时错误,而不是编译时错误)。
此外,它也不可组合。如果有三个选项,一个for comprehension 就可以照顾它们。
for {
  op1 <- opt1
  op2 <- opt2
  op3 <- opt3
} println(op1+op2+op3)

使用if语句,事情会很快变得混乱起来。


22

使用 foreach 的一个好处是可以解析带有嵌套选项的内容。 如果你有像下面这样的东西:

val nestedOption = Some(Some(Some(1)))
for {
  opt1 <- nestedOption
  opt2 <- opt1
  opt3 <- opt2
} println(opt3)

控制台打印 1。如果你将其扩展到一个类,该类可选择存储对某个东西的引用,而该东西又存储另一个引用,则推导式可以帮助你避免巨大的“金字塔”None/Some检查。


19

虽然有关于实际问题的优秀回答,但如果你想了解更多有关Option-foo的内容,你一定要看看Tony Morris的选项小抄


找到了这个页面,而不是上面的链接:http://tmorris.net/posts/2008-01-16-scalaoption-cheat-sheet.html - harmanjd
那张速查表真是太棒了。 - markhops

6

将类似于mapforeachflatMap这样的操作直接应用到Option上,而不是使用get然后执行函数,之所以更加有用,是因为它适用于Some或者None,你不需要进行特殊检查来确保值存在。

val x: Option[Int] = foo()
val y = x.map(_+1) // works fine for None
val z = x.get + 1  // doesn't work if x is None

这里的y的结果是一个Option[Int],这是可取的,因为如果x是可选的,那么y也可能是未确定的。由于get不能在None上工作,所以你需要做很多额外的工作来确保不会出现任何错误;而这些额外的工作都可以通过map为你完成。


是的,我指的是 get。我正在修复这篇文章。 - Michael

2

简单来说:

  • 如果你需要执行某些操作(不需要捕获每次调用的返回值)只有当选项已定义(即为Some)时:使用foreach(如果你关心每次调用的结果,使用map

  • 如果你需要在选项被定义时执行某些操作,否则执行其他操作:在if语句中使用isDefined

  • 如果你需要选项的值是Some,或者默认值是None:使用getOrElse


0
尝试使用get执行我们的操作更具命令式风格,需要告诉要做什么和如何做。换句话说,我们正在指示事情并深入挖掘Options内部。而map, flatmap是更功能性的做事方式,我们说要做什么但不是如何做

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接