我确定这是一个很好的理由,但我没有看到它。
(例如)Fold
上的 List
会返回
在所有元素和
之间应用折叠运算符op
z
的结果
它与foldLeft
和foldRight
有明显的关系,它们做同样的事情,但是定义了顺序(因此不需要关联运算符)
Fold
上的 Option
返回
如果
f
非空,则返回将scala.Option
应用于此scala.Option
值的结果。否则,计算表达式ifEmpty
。
ifEmpty
是列表的z
(位置)。 f
是op
对于None
(使用我的Option
心理模型作为"容器"可能包含或不包含值,是"空&#34 ;容器),一切正常,Option.fold
返回零(ifEmpty
的值)。
对于Some(x)
,不应该f
采用两个参数z
和x
,因此它与fold
一致在序列上(包括与foldLeft
和foldRight
具有相似的关系。)
肯定是针对此的实用程序论点 - 让f
在实践中将x
作为参数可能更方便。在大多数情况下,如果确实需要忽略z
。但是一致性也很重要......
所以有人可以向我解释为什么选项上的fold
仍然是"正确的" fold
?
答案 0 :(得分:2)
为什么会这样?
折叠“正常”采用二元运算符的原因是因为“正常”用于可以使用二元运算符(和种子值z)逐个处理的列表。
实际上,折叠选项是具有默认大小写的地图功能。如果你看一下它的定义,它的字面意思是:
if (isEmpty) ifEmpty else f(this.get)
由于您只有一个可能的参数,因此f必须是一元运算符。有人可能会争辩有一个选项fold,它接受一个二元运算符,并在定义选项的情况下使用ifEmpty值作为种子,但是你的合理种子值和当选项为空时的合理值可能会大不相同。
正如有人所指出的,对于不同的结构,你需要不同的元素(例如树木),因为减少的“合理”应用具有不同的结构。
答案 1 :(得分:0)
scala.Option.fold是一个错误; API设计不佳。
Option {
// This is equivalent to: map f getOrElse ifEmpty.
def fold[B](ifEmpty: => B)(f: A => B): B = if (isEmpty) ifEmpty else f(this.get)
}
Option.fold
方法可能很方便,但它不是fold
(同样适用于Either.fold
)。
TraversableOnce {
// List, et alia
def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 = foldLeft(z)(op)
}
标准方法的好处是概念和类型签名是一致的(无需再次审阅文档)。
此外,Option.foldLeft
一致,并且确实采用二元运算符。