Reputation: 22128
Apologies if this is a newbie question...
In Scala I understand that it is preferred to use an Option
rather than returning null
when you have a function which returns an instance but could potentially return nothing. I understand that this makes it better with regards to safety, because you are not passing null references around, and risking NullPointerException
somewhere down the line.
However, is there a cleaner way to handle options than using pattern matching? The syntax I end up using is the following:
val optObj : Option[MyObject] = myFunctionThatReturnsOption
optObj match {
case Some(obj) => {
//my code using obj
}
case None => _
}
In reality all this doing is the equivalent of the Java version:
MyObject obj = myMethodThatCanReturnNull()
if (obj != null) {
//my code using obj
}
Is there some other way to avoid all this boilerplate in Scala when using Option
instead of null
references? All I want to do is execute a piece of code as long as the Option
contains some object (i.e. is not None
).
Upvotes: 3
Views: 326
Reputation: 35980
Use foreach
, getOrElse
and/or map
if you want to work in a more consistent way. Here's some use cases and what I'd do:
//I want to get a non-null value and I have a sane default
val result = myOption getOrElse 3
//I want to perform some side effecting action but only if not None
myOption foreach{ value =>
println(value toString ())
}
//equivalently
for(value <- myOption){
//notice I haven't used the "yeild" keyword here
}
//I want to do a computation and I don't mind if it comes back as an Option
val result = for(value <- myOption) yield func(value)
val equivalent = myOption map func
The third example will use map
in both cases.
It gets really interesting when you can mix and match things in a "for comprehension" (Google term.) Let's say that func
also returns an Option
but I only want things working in specific cases:
val result = for{
value <- myOption if value > 0
output <- func(value)
} yield output
Now I get back an Option
but only if myOption
contained an integer that was greater than zero. Pretty nifty stuff, no?
Upvotes: 8
Reputation: 824
Here's a great reference for Scala best practices regarding options: http://blog.tmorris.net/posts/scalaoption-cheat-sheet/index.html
Upvotes: 1
Reputation: 3182
You can use the flatMap
-method pretty well with Option
. Like hier:
case class Player(name: String)
def lookupPlayer(id: Int): Option[Player] = {
if (id == 1) Some(new Player("Sean"))
else if(id == 2) Some(new Player("Greg"))
else None
}
def lookupScore(player: Player): Option[Int] = {
if (player.name == "Sean") Some(1000000) else None
}
println(lookupPlayer(1).map(lookupScore)) // Some(Some(1000000))
println(lookupPlayer(2).map(lookupScore)) // Some(None)
println(lookupPlayer(3).map(lookupScore)) // None
println(lookupPlayer(1).flatMap(lookupScore)) // Some(1000000)
println(lookupPlayer(2).flatMap(lookupScore)) // None
println(lookupPlayer(3).flatMap(lookupScore)) // None
Upvotes: 1
Reputation: 62835
Of course, the way I usually use options if I only care about present value is foreach:
optObj.foreach { obj =>
//...
}
Having said this, there are a lot of other options (which @wheaties enlisted) and some people keep battling about the true one.
Upvotes: 1
Reputation: 144136
You can use foreach
if you just want to perform some side-effecting operation with the value:
optObj.foreach(obj => {
//my code using obj
})
if you have some other use case you should use some other method on Option
like map
, filter
or getOrElse
.
Upvotes: 3