Option.map(null)返回Some(null)

时间:2015-04-15 20:48:03

标签: scala null

我希望此代码段返回None而不是Some(null)

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

我听说Scalaz库具有处理此类案例的功能。那么我如何使用scalaz和标准Scala库来实现我的目标?

3 个答案:

答案 0 :(得分:6)

您可以在此处使用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)

答案 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

但这是另一个故事。您可以找到有关此用例herevideo)的精彩说明。