Scala Option - Getting rid of if (opt.isDefined) {}
Solution 1
Maybe something like this:
somethingReturningAnOpt match {
case Some(actualThingIWant) => doSomethingWith(actualThingIWant)
case None =>
}
or as pst suggests:
somethingReturningAnOpt.foreach { actualThingIWant =>
doSomethingWith(actualThingIWant)
}
// or...
for (actualThingIWant <- somethingReturningAnOpt) {
doSomethingWith(actualThingIWant)
}
Solution 2
The canonical guide to Option wrangling is by Tony Morris.
Solution 3
Or:
somethingReturningAnOpt.map(doSomethingWith(_))
As in in:
val str = Some("foo")
str.map(_.toUpperCase)
... and use flatMap
when the result of doSomethingWith
is an Option itself.
val index = Option(Map("foo" -> "bar"))
index.flatMap(_.get("whatever")) // Returns None :-)
index.map(_.get("whatever")) // Returns Some(None) :-(
Solution 4
The following code cannot do something useful, since after the if
, actualThingIWant
is not always defined and as such this code will not compile, as long as you try to use actualThingIWant
later.
val opt = somethingReturningAnOpt
if (opt.isDefinedAt) {
val actualThingIWant = opt.get
}
So, you have to provide a default value. This can be achieved with getOrElse
:
val thingIWant = opt.getOrElse(myDefaultValue)
Or if you don't want to have actualThingIWant
after the body of the if
, which means you want to trigger some side-effects only if the option is defined, you can write:
opt.foreach{ thingIWant =>
println(thingIWant)
}
or a bit shorter
opt.foreach(println)
sanjay gouri
Updated on February 28, 2020Comments
-
sanjay gouri about 4 years
My code is becoming littered with the following code pattern:
val opt = somethingReturningAnOpt if (opt.isDefinedAt) { val actualThingIWant = opt.get }
Is there some way to simplify this? (it seems needlessly complex and a code smell). Ideally it would be something like:
if (Some(actualThingIWant) = somethingReturningAnOpt) { doSomethingWith(actualThingIWant) }
Is anything like that possible?
-
fanf42 over 12 yearsIt's worth noting that the for syntax allows to easily chain and compose option call: val optRes = for { res1 <- getOptRes1 ; res2 <- getOptRes2 } yield { doSomething(res1,res2) } /* here, res1 and res2 are not option, but the content, if available, and optRes will be an Option[TypeOfDoSomethingReturn] */
-
Dan Burton over 12 yearsPersonally I find case statements to be clearer for most situations; I'm not sure why Tony discourages them.
-
Duncan McGregor over 12 yearsI happen to agree with both comments!
-
cdmckay over 10 yearsYou could even shorten that to
somethingReturningAnOpt.map(doSomethingWith)
, no? -
TlmaK0 over 9 yearsI think this is the correct way to use Option monad
-
andresp over 6 yearsThis can only be used if the operation to execute for Some actually returns a value.
-
Suma about 3 yearsThis looks like a link only answer. Can you quote from the article, to make it more useful (and bring it up todays site standard)?
-
Duncan McGregor about 3 yearsFrankly, no. But if you want to add value to the world by paraphrasing someone else’s content just so that other people don’t have to click a link, please fill yer boots.