Scala Try的toOption方法返回Some(null)
Success
(Try的孩子Some(null)
在将其转换为Option
时返回Some(null)
?
例如Try(null).toOption
in scala 2.11.7返回Some(null)
Success的toOption
方法,只需返回Some(value)
。 为什么在转换Try
选项时使用toOption
方法返回None
,如果try的基础值为null
?
这里是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
绝对不。 Option不是一个空安全容器,它是一个Functor,Monad和一个大小为0或1的集合。它可以包含null,就像List一样。 就像尝试可以。
虽然它通常用于null安全,但由于Option.apply将null转换为None,并且避免使用null,因此一般Scala最佳实践也是如此。
此外,该语言不允许你定义一个不为null的类型参数,所以按照语言, Try[A]
隐含地说A可以为null, Option[A]
意味着该值也可以为null 。 A通常不是空的。
将包含空值的Try转换为None不正确,因为它会隐式地截断A的范围。 对于任何是AnyRef
A
, Some[A](null)
是有效的
语言设计与这里的最佳实践不符。 该语言无助于执行它。 空是有效的底部类型。 一个理想的世界将允许用户定义不可为空的类型,编译器可以跟踪空引入和消除,这将消除这些类型的意外。
请注意,如果我们使toOption
将null值转换为None,那么以下相等性不会成立:
val t: Try = ...
t.toOption.map(f) == t.map(f).toOption
当看似无害的重构完成时,这可能会导致代码中的其他惊喜,也许是对理解重新排序的一些小修改,由于操作顺序似乎与顺序无关,突然将结果从无变为其他。
斯卡拉应该有两种类型,一个是无效安全容器( Maybe
?),一般违反上述法律,因为它不能包含null,另一个就像今天的Option,但没有Option.apply - - 一个可选值。
Option.apply是一个奇怪的人,应该删除,国际海事组织。
例如,考虑以下内容,所有这些评估为Some(null)
:
Some(Some(null)).flatten
List("a", null).find(s != "a")
List(null, "blah").headOption
Try(null).toOption
选项用于整个集合库中的一个大小为0或1的集合,而不是一个空安全设备。 只要Option是一个大小为0或1的集合,而不是'非空'包装,它们就没有任何意义。 如果Option是这样的话,那么它将不会在集合库中用来表示可选值,例如上面的find
和headOption
。
如果有人真的想进入关于该主题的杂草,请尽情享受:https://groups.google.com/forum/#!msg/scala-internals/1DXdknjt9pY/_moEcbNd4noJ
5年前,我认为这是摆脱Some(null)
的好主意。 现在我会建议摆脱Option.apply
并为non-nullness创建一个不同的类型。 称它为Maybe
。 然后可以Try.toMaybe
旁边Try.toOption