Scala Option - Getting rid of if (opt.isDefined) {}

21,807

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)
Share:
21,807
sanjay gouri
Author by

sanjay gouri

Updated on February 28, 2020

Comments

  • sanjay gouri
    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
    fanf42 over 12 years
    It'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
    Dan Burton over 12 years
    Personally I find case statements to be clearer for most situations; I'm not sure why Tony discourages them.
  • Duncan McGregor
    Duncan McGregor over 12 years
    I happen to agree with both comments!
  • cdmckay
    cdmckay over 10 years
    You could even shorten that to somethingReturningAnOpt.map(doSomethingWith), no?
  • TlmaK0
    TlmaK0 over 9 years
    I think this is the correct way to use Option monad
  • andresp
    andresp over 6 years
    This can only be used if the operation to execute for Some actually returns a value.
  • Suma
    Suma about 3 years
    This 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
    Duncan McGregor about 3 years
    Frankly, 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.