为什么没有选项有折叠方法?
我想知道为什么scala.Option没有像这样定义的方法fold :
fold(ifSome: A => B , ifNone: => B)
相当于
map(ifSome).getOrElse(ifNone)
有没有比使用map + getOrElse更好?
你可以做:
opt foldLeft (els) ((x, y) => fun(x))
要么
(els /: opt) ((x,y) => fun(x))
(这两个解决scheme都会 根据价值 评估 els ,这可能不是你想要的。感谢Rex Kerr指出了这一点。)
编辑:
但是,你真正想要的是斯卡拉斯的变形 cata (基本上是一个fold ,不仅处理Some值,而且映射None部分,这是你所描述的)
opt.cata(fun, els)
定义为(其中value是pimped选项值)
def cata[X](some: A => X, none: => X): X = value match { case None => none case Some(a) => some(a) }
相当于opt.map(some).getOrElse(none) 。
虽然我应该说,只有在“更自然”的expression方式时才应该使用cata。 有很多情况下,一个简单的map – getOrElse就足够了,尤其是当它涉及到可能链接大量的map 。 (当然,你也可以把function组合连锁在一起,这取决于你是想把重点放在function组合还是价值转换上。)
我个人觉得像cata这样以两个封闭为参数的方法经常是过度的。 你真的通过map + getOrElse获得可读性吗? 想想你的代码的新手:他们会做什么
opt cata { x => x + 1, 0 }
你真的觉得比这更清楚吗?
opt map { x => x + 1 } getOrElse 0
事实上,我会争辩说,对于那些古老的人来说,这两者都不是好事
opt match { case Some(x) => x + 1 case None => 0 }
与往常一样,额外的抽象不会给您带来好处,并且会产生相反的效果。
它最终被添加到Scala 2.10 ,带有签名fold[B](ifEmpty: => B)(f: A => B): B 。
正如Debilski所提到的,你可以使用Scalaz的OptionW.cata或者fold 。 正如贾森评论说,命名参数使这看起来不错:
opt.fold { ifSome = _ + 1, ifNone = 0 }
现在,如果对于某些Monoid[M] ,在None情况下你想要的值是mzero对于某些情况你有一个函数f: A => M ,你可以这样做:
opt foldMap f
所以,
opt map (_ + 1) getOrElse 0
变
opt foldMap (_ + 1)
就个人而言,我认为Option应该有一个apply方法,这将是变形。 这样你就可以做到这一点:
opt { _ + 1, 0 }
要么
opt { some = _ + 1, none = 0 }
事实上,对于所有的代数数据结构来说,这将是很好的。