如何在 Scala 中组合 Option 值?
我希望能够应用操作 f: (T,T) => Scala 中的 T
到 Option[T]
值。如果两个值中的任何一个为 None
,我希望结果为 None
。
更具体地说,我想知道是否有更短的方法来执行以下操作:
def opt_apply[T](f: (T,T) => T, x: Option[T], y: Option[T]): Option[T] = {
(x,y) match {
case (Some(u),Some(v)) => Some(f(u,v))
case _ => None
}
}
我已尝试 (x zip y) map {case (u,v) =>; f(u,v)}
但结果是一个 Iterator[T]
而不是 Option[T]
。
I want to be able to apply an operation f: (T,T) => T
to Option[T]
values in Scala. I want the result to be None
if any of the two values is None
.
More specifically, I want to know if there is a shorter way to do the following:
def opt_apply[T](f: (T,T) => T, x: Option[T], y: Option[T]): Option[T] = {
(x,y) match {
case (Some(u),Some(v)) => Some(f(u,v))
case _ => None
}
}
I have tryied (x zip y) map {case (u,v) => f(u,v)}
but the result is an Iterator[T]
not an Option[T]
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
@RahulG 的答案利用了
Option
是一个 monad 的事实(尽管 Scala 库中没有类型来表示它)。编译器将for
理解扩展为以下内容:在 Scalaz 的帮助下,您还可以将其视为应用函子:
一个关键的区别是,在单子计算中,失败(即 < code>None) 的计算
a
会短路评估。在应用风格中,a
和b
都会被求值,如果两者都是Some
,则调用纯函数。您还可以看到,在一元计算中,值aa
可能已在计算b
中使用;在应用版本中,b
不能依赖于a
的结果。@RahulG's answer exploits the fact that
Option
is a monad (even though there is no type to represent this in the Scala library). The compiler expands thefor
comprehension to the following:You can also treat it as an applicative functor, with some help from Scalaz:
A key difference is that in the monadic calculation, a failure (that is,
None
) of calculationa
short circuits the evaluation. In the applicative style, botha
andb
are evaluated, and if both areSome
s, the pure function is called. You can also see that in the monadic calculation, the valueaa
could have been used in the calculationb
; in the applicative version,b
cannot depend on the result ofa
.我的 scalaz 版本比 retronym 稍旧,但以下内容对我来说是一个示例,并且可以推广到有 3 种类型
T、U 的情况、V
而不仅仅是一个:然后我可以添加:
I have a slightly older version of scalaz than retronym but the following works for me as an example and is generalizable for the case where you have 3 types
T, U, V
and not just one:I can then add:
从 Scala 2.13 开始,
Option#zip
可以应用于另一个Option
返回一个Option
(在早期版本中,它会返回一个Iterable
);因此:zip 的行为是:
并且可以这样应用:
Starting
Scala 2.13
,Option#zip
can be applied to anotherOption
to return anOption
(in earlier versions, it would have returned anIterable
); thus:where the behavior of
zip
is:and which can be applied as such:
您可以用于理解:
Which is Sugar for:
这也是可能的,因为 Option 是 Monad
You can use for comprehensions:
Which is sugar for:
This is also possible due to Option being a Monad
a.zip(b)
确实会产生一个 Iterable[(A, B)] (因为它来自 Options,所以最多有一个元素)。然后headOption
返回第一个元素作为选项。a.zip(b)
does result in an Iterable[(A, B)] (with, because it's from Options, at most one element).headOption
then returns the first element as an Option.