Option.map (null) 返回一些 (null)



我想让这个代码片段返回我None而不是Some(null)

Option(x).map(x.getNullValue) // returns Some(null)

我听说Scalaz库有处理这种情况的功能。那么如何使用scalaz和标准 Scala 库来实现我的目标呢?

您可以在此处将flatMapOption.apply 方法一起使用,而不是拉入scalaz

Option(initialValue).flatMap(x => Option(x.getNullValue))

这是有效的,因为Option.apply方法智能地踏null

val x: String = null
Option(x) //None
Option("foo") //Some("foo")

因此,如果您完全了解其价值,则可以简单地执行以下操作:

Option(x.getNullValue)

您也可以在Option上使用其他方法,如filterorElsegetOrElse,具体取决于情况:

Option(initialValue).map(_.getNullValue).filter(_ != null)
Option(initialValue).orElse(Option(x.getNullValue))
Option(x.getNullValue).getOrElse(defaultValue)

我不了解 scalaz,但在标准库中,您唯一的选择实际上是过滤掉null值。 map只是简单地映射A => B并期望B不会被null

例:

object HasNull {
    def getNull: Any = null
}
scala> Option(HasNull).map(_.getNull).filter(_ != null)
res24: Option[Any] = None

scala> Option(HasNull).flatMap(a => Option(a.getNull))
res25: Option[Any] = None

或者,您可以使用一些隐式魔法来避免Option样板:

implicit def toOpt[A](a: A): Option[A] = Option(a)
scala> Option(HasNull).flatMap(_.getNull)
res3: Option[Any] = None

使用flatMap仍然是关键,因为它期望Option[B]。但是getNull是类型 B ,因此将使用隐式转换,这将再次将 nullable 包装在 Option.apply 中。

正如其他人已经写过的,你可以使用flatMap来做到这一点。一个非常相似的方法是:

case class User(name: String)
val users = List(null, User("John"), User(null))
for{
  userDb <- users
  user <- Option(userDb)
  name <- Option(user.name)
} yield name

None的问题在于你不知道你得到了哪个None:用户不存在或名称?在这种情况下,scalaz可以帮助您:

for{
  userDb <- users
  user <- Option(userDb) /> "No user found."
  name <- Option(user.name) /> "No name provided."
} yield name

但这是另一回事了。您可以在此处找到有关此用例的精彩解释(视频)。

最新更新