I want to this code snippet return me None
instead of Some(null)
:
Option(x).map(x.getNullValue) // returns Some(null)
I heard Scalaz
library has features to handle such case. So how I can achieve my goal using both: scalaz
and standard Scala library?
You could use flatMap
together with the Option.apply
method here instead of pulling in scalaz
:
Option(initialValue).flatMap(x => Option(x.getNullValue))
This works since the Option.apply
method treads null
intelligently:
val x: String = null
Option(x) //None
Option("foo") //Some("foo")
So if you know the value outright, you can simply do:
Option(x.getNullValue)
You can also use other methods on Option
like filter
, orElse
, or getOrElse
, depending on the situation:
Option(initialValue).map(_.getNullValue).filter(_ != null)
Option(initialValue).orElse(Option(x.getNullValue))
Option(x.getNullValue).getOrElse(defaultValue)
I don't know about scalaz, but in the standard library your only choice really is to filter out the null
value. map
simply maps A => B
and expects that B
will not be null
.
Example:
object HasNull {
def getNull: Any = null
}
scala> Option(HasNull).map(_.getNull).filter(_ != null)
res24: Option[Any] = None
Or
scala> Option(HasNull).flatMap(a => Option(a.getNull))
res25: Option[Any] = None
Alternatively, you can use a little implicit magic to avoid the Option
boilerplate:
implicit def toOpt[A](a: A): Option[A] = Option(a)
scala> Option(HasNull).flatMap(_.getNull)
res3: Option[Any] = None
Using flatMap
still is the key, because it expects an Option[B]
. But getNull
is of type B
, so the implicit conversion will be used, which will wrap the nullable in Option.apply
again.
As others already wrote, you can do it using flatMap. And a very similar approach is:
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
The problem with None
is that you do not know which None
you get: user doesn't exist or name? In this case scalaz can help you:
for{
userDb <- users
user <- Option(userDb) \/> "No user found."
name <- Option(user.name) \/> "No name provided."
} yield name
But this is another story. You can find awesome explanation about this use case here (video).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With