Scala Try的toOption方法返回Some(null)

时间:2015-12-18 11:49:57

标签: scala

Success转换为Some(null)时,Option(Try的孩子)应该返回Try(null).toOption吗?

E.g。 scala 2.11.7中的Some(null)返回toOption 只需返回Some(value)即可实现成功的None方法。 如果try的基础值为Try,则在使用toOption方法将null转换为选项时,为什么不返回No Moves left

2 个答案:

答案 0 :(得分:4)

以下是Scala 2.11.7中toOption的来源:

def toOption: Option[T] = if (isSuccess) Some(get) else None

我同意布鲁诺的观点,这令人困惑,应该阅读

def toOption: Option[T] = if (isSuccess) Option(get) else None

答案 1 :(得分:0)

绝对不是。 Option不是一个null安全容器,它是一个Functor,一个Monad,以及一个大小为0或1的Collection。它可以包含null,就像List一样。就像Try can。

虽然它经常用于null安全,但是由于Option.apply将null转换为None以及一般的Scala最佳实践,避免使用null。

此外,该语言不允许您定义非null的类型参数,因此Try[A]隐含地表示根据语言A可以为null,而Option[A]表示value也可以为null。按惯例,A通常不为空。

将包含空值的Try转换为None是不正确的,因为它会隐式截断A的范围。对于Some[A](null)

的任何AAnyRef有效

语言设计与此处的最佳实践不一致。该语言几乎没有任何帮助来强制执行它。 Null是有效的底部类型。一个理想的世界将允许用户定义非可空类型和编译器来跟踪空引入和消除,这将消除这些意外。

请注意,如果我们将toOption转换为空值为None,则以下等式将不成立:

val t: Try = ...
t.toOption.map(f) == t.map(f).toOption

当看似无害的重构完成时,可能会导致代码中出现其他惊喜,也许是因为出现的操作顺序而导致理解重新排列突然将结果从None更改为其他内容时的一些小错误独立于订单。

Scala应该有两种类型,一种是空安全容器(Maybe?)并且一般违反上面的法律,因为它不能包含null,而另一种就像今天的选项一样,但没有Option.apply - 一个可选值。

Option.apply是奇怪的人,应该被删除,IMO。

例如,请考虑以下因素,所有这些评估为Some(null)

Some(Some(null)).flatten
List("a", null).find(s != "a")
List(null, "blah").headOption
Try(null).toOption

选项在整个集合库中用作大小为0或1的集合,而不是空安全设备。只要Option是一个大小为0或1的主要集合,而不是一个'非null'包装器,返回None就没有意义。如果Option是这样的,那么它不会在集合库中用于表示可选值,例如上面的findheadOption

如果有人真的想要了解这个主题的杂草,那就玩得开心: https://groups.google.com/forum/#!msg/scala-internals/1DXdknjt9pY/_moEcbNd4noJ

5年前我认为摆脱Some(null)是一个好主意。现在我建议删除Option.apply并为非null值创建不同的类型。称之为Maybe。然后,可以在Try.toMaybe

旁边Try.toOption