我希望此代码段返回None
而不是Some(null)
:
Option(x).map(x.getNullValue) // returns Some(null)
我听说Scalaz
库具有处理此类案例的功能。那么我如何使用scalaz
和标准Scala库来实现我的目标?
答案 0 :(得分:6)
您可以在此处使用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)
答案 1 :(得分:2)
我不了解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
,因此将使用隐式转换,这将再次将{0}中的可空包裹起来。
答案 2 :(得分:1)
正如其他人已经写过的那样,你可以使用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