2015-04-15 64 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)。