9

如果设置了选项的值,我想执行一些逻辑。

来自java背景,我用过:

if (opt.nonEmpty) {
   //something
}

再深入一点,我可以这样写:

opt.foreach(o => {
  //something 
})

哪一个更好?“foreach” 听起来更“惯用”,Java 更少,但可读性更差——应用于单个值的“foreach”听起来很奇怪。

4

4 回答 4

18

您的示例不完整,并且您没有使用最少的语法。只需比较这两个版本:

if (opt.nonEmpty) {
  val o = opt.get
  // ...
}

// vs

opt foreach {
  o => // ...
}

if (opt.nonEmpty)
  doSomething(opt.get)

// vs

opt foreach doSomething

在这两个版本中,解决方案都有更多的语法开销if,但我同意,如果您仅将其视为可选值, foreachon an可能会令人困惑。Option

相反foreach,它描述了您想要做某种副作用,如果您认为自己Option是一个 monad 并且foreach只是一种转换它的方法,那么这很有意义。此外, Usingforeach的巨大优势在于它使重构更容易 - 您可以将其类型更改为 aList或任何其他 monad,并且不会出现任何编译器错误(因为 Scalas 强大的集合库,您不会被限制只使用适用于monads,在很多类型上定义了很多方法)。

于 2013-08-10T16:32:51.230 回答
10

foreach does make sense, if you think of Option as being like a List, but with a maximum of one element.

A neater style, IMO, is to use a for-comprehension:

for (o <- opt) {
  something(o)
}
于 2013-08-10T16:25:28.977 回答
6

foreachOption如果您认为是一个最多可以包含一个值的列表,那么这是有道理的。这也导致了对许多其他可用方法的正确直觉Option

在这种情况下,我至少可以想到一个您可能更喜欢的重要原因foreach:它消除了可能的运行时错误。使用这种nonEmpty方法,您有时必须执行一个get*,如果您不小心忘记检查是否为空,这可能会使您的程序严重崩溃。

如果你完全get从你的脑海中抹去以避免那种错误,副作用是你也少用了nonEmpty!而且您将开始享受并让编译器处理如果碰巧为空foreach应该发生的事情。Option

你会看到这个概念出现在其他地方。你永远不会做

if (age.nonEmpty)
    Some(age.get >= 18)
else
    None

你更愿意看到的是

age.map(_ >= 18)

原则是您希望避免编写处理失败情况的代码——您希望将这种负担卸载给编译器。许多人会告诉你,你永远不应该使用get,无论你认为你对预检查有多小心。所以这让事情变得更容易。


* 除非您实际上只是想知道 是否Option包含一个值并且并不真正关心该值,在这种情况下nonEmpty就可以了。在这种情况下,它充当一种toBoolean.

于 2013-08-10T16:31:10.253 回答
2

我在其他答案中没有找到的东西:

  1. 使用 时if,我更喜欢前者if (opt isDefined)if (opt nonEmpty)因为前者不像集合,并且更清楚地表明我们正在处理一个选项,但这可能是一个品味问题。

  2. if并且foreach在某种意义上是不同的,即在返回if时将返回值的表达式。因此,在某种程度上, using甚至比 更类似于java,因为 java 有一个 foreach 循环,而 java's不是表达式。使用 for 理解更类似于 scala。foreachUnitforeachifif

  3. 您也可以使用模式匹配(但这也不太惯用)

  4. 您可以使用该fold方法,它采用两个函数,因此您可以在 case 中评估一个表达式,在Somecase中评估另一个表达式None。由于类型推断的工作原理,您可能需要显式指定预期类型(如此处所示。所以在我看来,有时使用模式匹配或val result = if (opt isDefined) expression1 else expression2.

如果您不需要返回值并且确实不需要处理未定义的情况,则可以使用foreach.

于 2013-12-11T10:56:43.060 回答