Scala if(Option.nonEmpty)与Option.foreach
如果设置了选项的值,我想执行一些逻辑 来自java背景,我使用:Scala if(Option.nonEmpty)与Option.foreach,scala,Scala,如果设置了选项的值,我想执行一些逻辑 来自java背景,我使用: if (opt.nonEmpty) { //something } 再深入到scala,我可以这样写: opt.foreach(o => { //something }) 哪一个更好?“foreach”一词听起来更“惯用”,Java更少,但可读性较差——“foreach”应用于单个值听起来很奇怪。foreach如果您认为选项类似于列表,但最多只有一个元素,那么它确实有意义 一种更简洁的风格,IMO,是使用一个
if (opt.nonEmpty) {
//something
}
再深入到scala,我可以这样写:
opt.foreach(o => {
//something
})
哪一个更好?“foreach”一词听起来更“惯用”,Java更少,但可读性较差——“foreach”应用于单个值听起来很奇怪。
foreach
如果您认为选项
类似于列表,但最多只有一个元素,那么它确实有意义
一种更简洁的风格,IMO,是使用一个字母来理解:
for (o <- opt) {
something(o)
}
<代码> >(o> p> <代码>前缀 >如果您认为<代码>选项>代码>可以是最多包含单个值的列表。这也会导致对<代码>选项> <代码> > 的许多其他方法的正确直觉。
在这种情况下,我至少可以想到一个重要的原因,您可能更喜欢使用foreach
:它删除了可能的运行时错误。使用非空的方法,您将不得不在某一点上执行get
*,如果您意外地忘记检查一次是否为空,这可能会使您的程序崩溃
如果您完全清除了get
以避免此类错误,那么副作用是nonEmpty
的使用也会减少!您将开始享受foreach
的乐趣,并让编译器处理选项恰好为空时应该发生的事情
你会看到这个概念在其他地方突然出现,你永远不会这么做
if (age.nonEmpty)
Some(age.get >= 18)
else
None
你宁愿看到的是
age.map(_ >= 18)
原则是,您希望避免编写处理故障情况的代码–您希望将这一负担卸给编译器。许多人会告诉您,无论您多么小心地进行预检查,都不应该使用get
。这样做会使事情变得更简单
*除非您实际上只是想知道选项是否包含值,而不是真正关心值,否则在这种情况下非空
就可以了。在这种情况下,它就像是一种toBoolean
,您的示例不完整,并且没有使用最小语法。只需比较这两个版本:
if (opt.nonEmpty) {
val o = opt.get
// ...
}
// vs
opt foreach {
o => // ...
}
及
在这两个版本中,if
解决方案的语法开销都比较大,但我同意,如果将选项
上的foreach
仅视为一个可选值,则可能会造成混淆
相反,foreach
描述了你想要做一些副作用,如果你认为选项
是一个单子,而foreach
只是一个转换它的方法,这是很有意义的。使用foreach
还有一个巨大的优势,那就是它使重构更容易——你只需改变它的类型到列表
或任何其他monad,您将不会得到任何编译器错误(由于Scalas great collections library,您不必仅使用在monad上工作的操作,在许多类型上定义了许多方法)。我在其他答案中没有找到的东西:
当使用if
时,我更喜欢if(opt-isDefined)
而不是if(opt-nonEmpty)
,因为前者不像集合,并且更清楚地表明我们正在处理一个选项,但这可能是一个品味问题
if
和foreach
是不同的,因为if
是一个返回值的表达式,而foreach
返回Unit
。因此在某种程度上使用foreach
比if
更像java,因为java有一个foreach循环,而java的if
不是表达式。使用a表示理解更像scala
您还可以使用模式匹配(但这也不太惯用)
您可以使用fold
方法,该方法具有两个函数,因此您可以在Some
情况下计算一个表达式,在None
情况下计算另一个表达式。由于类型推断的工作方式,您可能需要显式指定预期的类型(如图所示)因此,在我看来,有时使用模式匹配或val result=if(opt isDefined)表达式1 else表达式2
可能更为清晰
如果您不需要返回值,并且确实不需要处理未定义的情况,那么可以使用foreach
我喜欢这种推理。我还想补充一点,使用foreach时,您永远不会在代码中引入get()
,即使正确测试非空()
。如果无论选项是否为空,都需要执行某些操作,将
与Some(x)
和None
案例匹配。在您的第一个代码片段中,它不应该是Some(age.get>=18)
是否也有一个选项作为结果类型?@berylium当然应该!我不知道这是怎么发生的。可能是因为太多Python了。“据我所知,没有一个选项方法可以在某些情况下对一个表达式求值,而在无情况下对另一个表达式求值”有:opt.fold(“None”)(v=>s“Some($v)”
。
if (opt.nonEmpty)
doSomething(opt.get)
// vs
opt foreach doSomething