2015-04-15 58 views
2

我想这个代码片段返回我None,而不是Some(null)Option.map(空)返回一些(空)

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

听说Scalaz图书馆功能来处理这种情况。那么我怎样才能实现我的目标:scalaz和标准的Scala库?

+2

'Option(x.getNullValue)'有什么问题? – ipoteka

+1

@ipoteka'x'也可以为null,所以我也把它换成'Option' – MyTitle

回答

3

你可以与Option.apply方法一起使用flatMap这里,而不是在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) 

您也可以使用其他方法对OptionfilterorElse,或getOrElse,根据不同的情况:

Option(initialValue).map(_.getNullValue).filter(_ != null) 
Option(initialValue).orElse(Option(x.getNullValue)) 
Option(x.getNullValue).getOrElse(defaultValue) 
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,因此将使用隐式转换,它将再次将可空对象包含在Option.apply中。

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)。