質問

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?

役に立ちましたか?

解決

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)
}

他のヒント

The canonical guide to Option wrangling is by Tony Morris.

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) :-(

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)
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top