if(Option.nonEmpty)vs Option.foreach

Boz*_*zho 9 scala

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

来自java背景,我用过:

if (opt.nonEmpty) {
   //something
}
Run Code Online (Sandbox Code Playgroud)

进一步了解scala,我可以写为:

opt.foreach(o => {
  //something 
})
Run Code Online (Sandbox Code Playgroud)

哪一个更好?"foreach"听起来更"惯用"而且Java更少,但它的可读性更低 - 应用于单个值的"foreach"听起来很奇怪.

kir*_*uku 18

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

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

// vs

opt foreach {
  o => // ...
}
Run Code Online (Sandbox Code Playgroud)

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

// vs

opt foreach doSomething
Run Code Online (Sandbox Code Playgroud)

在两个版本中有更多的句法开销if的解决方案,但我认为,foreach在一个Option可能会造成混淆,如果你认为它只是作为一个可选值.

而是foreach描述你想要做某种副作用,如果你想Option成为一个monad并且foreach只是一个改变它的方法,那么这很有意义.使用foreach还有一个很大的优点,它使重构更容易 - 你可以只改变它的类型List或任何其他monad你不会得到任何编译器错误(因为Scalas伟大的集合库你不限制只使用工作的操作monads,在很多类型上定义了很多方法).

  • 我喜欢这个推理.我还要补充一点,在foreach中你永远不会在你的代码中引入`get()`,即使你正确地测试`nonEmpty()`,这也是一个`Option`的坏习惯.如果你需要做一些事情,无论选项是否为空,那么`匹配'与`Some(x)`和`None`的情况是可行的. (2认同)

Ben*_*mes 10

foreach确实有意义,如果你认为Option它像一个List,但最多只有一个元素.

一个更整洁的风格,IMO,是使用理解:

for (o <- opt) {
  something(o)
}
Run Code Online (Sandbox Code Playgroud)


kqr*_*kqr 6

foreach如果你认为Option是一个最多只能包含一个值的列表,那就有意义了.这也导致了对可用的许多其他方法的正确直觉Option.

foreach在这种情况下,我至少可以想到您可能想要的一个重要原因:它可以消除可能的运行时错误.通过这种nonEmpty方法,你将在某一点上必须做一个get*,如果你偶然忘记检查空虚,这可能会使你的程序崩溃.

如果你完全get从头脑中消除以避免这种错误,那么副作用就是你也没那么用了nonEmpty!并且你将开始享受foreach并让编译器处理如果Option恰好是空的应该发生的事情.

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

if (age.nonEmpty)
    Some(age.get >= 18)
else
    None
Run Code Online (Sandbox Code Playgroud)

你宁愿看到的是什么

age.map(_ >= 18)
Run Code Online (Sandbox Code Playgroud)

原则是您希望避免编写处理故障情况的代码 - 您希望将此负担卸载到编译器.许多人会告诉你,你永远不应该使用get,不管你认为你是在预先检查.这样可以简化事情.


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