我想让这个代码片段返回我None
而不是Some(null)
:
Option(x).map(x.getNullValue) // returns Some(null)
我听说Scalaz
库有处理这种情况的功能。那么如何使用scalaz
和标准 Scala 库来实现我的目标呢?
您可以在此处将flatMap
与 Option.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
上使用其他方法,如filter
、orElse
或getOrElse
,具体取决于情况:
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
但这是另一回事了。您可以在此处找到有关此用例的精彩解释(视频)。