为什么 Option 没有折叠方法?
我想知道为什么 scala.Option
没有这样定义的方法 fold
:
fold(ifSome: A => B , ifNone: => B)
相当于
map(ifSome).getOrElse(ifNone)
是否没有比使用 map
+ getOrElse
?
I wonder why scala.Option
doesn't have a method fold
like this defined:
fold(ifSome: A => B , ifNone: => B)
equivalent to
map(ifSome).getOrElse(ifNone)
Is there no better than using map
+ getOrElse
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我个人发现像
cata
这样采用两个闭包作为参数的方法通常做得太过分了。你真的比map
+getOrElse
提高了可读性吗?想想你的代码的新人:他们会做什么你真的认为这比旧的更清晰吗
事实上我认为这两者都不比旧的好
一如既往,存在一个限制,额外的抽象不会给你带来好处和转变适得其反。
I personally find methods like
cata
that take two closures as arguments are often overdoing it. Do you really gain in readability overmap
+getOrElse
? Think of a newcomer to your code: What will they make ofDo you really think this is clearer than
In fact I would argue that neither is preferable over the good old
As always, there's a limit where additional abstraction does not give you benefits and turns counter-productive.
它最终被添加到 Scala 2.10 中,其中签名
fold[B](ifEmpty: => B)(f: A => B): B
。不幸的是,这会带来一个常见的负面后果:仅根据
ifEmpty
参数推断出 B 调用,而实际上,该参数的范围通常更窄。例如(标准库中已经有正确的版本,这仅用于演示)Scala 会将
B
推断为Nil.type
而不是所需的List[A ]
并抱怨f
没有返回Nil.type
。相反,您需要其中之一。这使得
fold
并不完全等同于相应的match
。It was finally added in Scala 2.10, with the signature
fold[B](ifEmpty: => B)(f: A => B): B
.Unfortunately, this has a common negative consequence:
B
is inferred for calls based only on theifEmpty
argument, which is in practice often more narrow. E.g. (a correct version is already in the standard library, this is just for demonstration)Scala will infer
B
to beNil.type
instead of desiredList[A]
and complain aboutf
not returningNil.type
. Instead, you need one ofThis makes
fold
not quite equivalent to correspondingmatch
.您可以执行以下操作:
或
(两种解决方案都会按值评估
els
,这可能不是您想要的。感谢Rex Kerr 指出了它。)编辑:
但你真正想要的是 Scalaz 的 catamorphism
cata
(基本上是一个fold
,它不仅处理Some
值,但也映射None
部分,这就是您所描述的)定义为(其中
value
是 pimped 选项值),这是等效的到
opt.map(some).getOrElse(none)
。尽管我应该指出,只有当 cata 是“更自然”的表达方式时才应该使用它。在许多情况下,一个简单的
map
-getOrElse
就足够了,特别是当它涉及潜在链接大量map
时。 (当然,尽管您也可以将fun
与函数组合链接起来——这取决于您是否想专注于函数组合或值转换。)You can do:
or
(Both solutions will evaluate
els
by value, which might not be what you want. Thanks to Rex Kerr for pointing at it.)Edit:
But what you really want is Scalaz’s catamorphism
cata
(basically afold
which not only handles theSome
value but also maps theNone
part, which is what you described)defined as (where
value
is the pimped option value)which is equivalent to
opt.map(some).getOrElse(none)
.Although I should remark that you should only use cata when it is the ‘more natural’ way of expressing it. There are many cases where a simple
map
–getOrElse
suffices, especially when it involves potentially chaining lots ofmap
s. (Though you could also chain thefun
s with function composition, of course – it depends on whether you want to focus on the function composition or the value transformation.)正如 Debilski 提到的,您可以使用 Scalaz 的
OptionW.cata
或fold
。正如 Jason 所评论的,命名参数使这看起来很不错:现在,如果您在
None
情况下想要的值是mzero
对于某些Monoid[M]
> 并且你有一个函数f: A =>; M
对于Some
情况,你可以这样做:所以,
变成
个人而言,我认为
Option
应该有一个apply
方法将是变形现象。这样你就可以这样做:或者
事实上,这对于所有代数数据结构来说都是很好的。
As mentioned by Debilski, you can use Scalaz's
OptionW.cata
orfold
. As Jason commented, named parameters make this look nice:Now, if the value you want in the
None
case ismzero
for someMonoid[M]
and you have a functionf: A => M
for theSome
case, you can do this:So,
becomes
Personally, I think
Option
should have anapply
method which would be the catamorphism. That way you could just do this:or
In fact, this would be nice to have for all algebraic data structures.