Reputation: 1
Consider example
object Main extends App {
case class ref(val target: Object)
val map: Map[Int, ref] = Map(1 -> ref(null), 2 -> ref("2"))
//> map : Map[Int,o.ref] = Map(1 -> ref(null), 2 -> ref(2))
def request(id: Int, default: Object) = {
println(map.get(id) map (_.target) match {
case Some(result) => result
case None => default
})
} //> request: (id: Int, default: Object)Unit
request(0, "fixed 0") //> fixed 0
request(1, "fixed 1") //> null
request(2, "fixed 2") //> 2
}
As you see, option1 results in null. I want such targets to handle likewise there is no match in the db. How do I convert Some(null)
to None
?
Upvotes: 2
Views: 1755
Reputation: 28056
Calling map.get(1)
will return Some(ref(null))
. Doing Some(ref(null)) map (_.target)
results in Some(null)
. That is why you get null. You could do this instead:
def request(id: Int, default: Object) = {
println(map.get(id).flatMap(r => Option(r.target)).getOrElse(default))
}
Now request(1, "fixed 1")
will print fixed 1
.
Also, your final match
expression can be shortened to getOrElse(default)
.
Upvotes: 0
Reputation: 22206
In general, if you want to convert a value that may be null
into an Option
, just build it like so:
Option(ref)
In your case, since you want an inner field to become an Option
, you can just flatMap
:
map.get(id).flatMap(ref => Option(ref.target))
I would rewrite your request
method so:
def request(id: Int, default: Object) =
println(map.get(id).flatMap(ref => Option(ref.target)).getOrElse(default))
Option
's apply method does exactly what you want, if you pass it a null
, it will return a None
, that's how the flatMap
bit works.
Upvotes: 2
Reputation: 1
Up do date, my best match was to use flatMap
map (_.target) flatMap { case null => None ; case a => Some(a) }
Upvotes: 1