5

Suppose, I have two options:

val a: Option = Some("string")
val b: Option = None

How to efficiently check that both a and b is defined?

I now that I can wrote something like this:

if (a.isDefined && b.isDefined) {
....
}

But, it looks ugly and not efficiently.

So. How to do that? What is best practices?

UPDATE

I want to do my business logic.

if (a.isDefined && b.isDefined) {
   ....

   SomeService.changeStatus(someObject, someStatus)

   ...
   /* some logic with a */
   /* some logic with b */
}
atygaev.mi
  • 144
  • 2
  • 11
  • 2
    It depends, what do you want to do with the options if both are defined? As far as efficiency goes, your current solution is probably the fastest (though it's probably not worth worrying too much about that) – Ryan Apr 09 '14 at 23:30
  • Thanks, for reply. I want to do my business logic with this **a** and **b** – atygaev.mi Apr 09 '14 at 23:55

3 Answers3

7

Use a for comprehension:

val a: Option[String] = Some("string")
val b: Option[String] = None

for {
    aValue <- a
    bValue <- b
} yield SomeService.changeStatus(someObject, someStatus)
Noah
  • 13,821
  • 4
  • 36
  • 45
  • 1
    Is this more efficient than `if (a.isDefined && b.isDefined) SomeService.changeStatus(someObject, someStatus)`? It definetly seems more obscure. – Dominykas Mostauskis Apr 10 '14 at 10:27
  • It's probably slightly less efficient because it becomes `a.flatMap(aValue => b.map(bValue => ... ))`. However, this is the idiomatic way to work `Option` in scala and prevents a class of errors that `Option` is designed to protect you from. – Noah Apr 10 '14 at 12:36
  • Can this pattern also be used for a `List[Option[...]]` where the size is not known at compile time? – ComFreek Feb 13 '19 at 08:22
6

Alternatively, just for fun,

scala> val a: Option[String] = Some("string")
a: Option[String] = Some(string)

scala> val b: Option[String] = None
b: Option[String] = None

scala> val c = Option("c")
c: Option[String] = Some(c)

scala> (a zip b).nonEmpty
res0: Boolean = false

scala> (a zip c).nonEmpty
res1: Boolean = true

scala> (a zip b zip c).nonEmpty
res2: Boolean = false
som-snytt
  • 39,429
  • 2
  • 47
  • 129
1

I was looking at this and needed to handle each combination differently, so I went for a match:

val a: Option[String] = Some("a")
val b: Option[String] = None

(a, b) match {
  case (Some(aStr), Some(bStr)) => ???
  case (Some(aStr), None      ) => ???
  case (None,       Some(bStr)) => ???
  case (None,       None      ) => ???
}
Robert Elliot
  • 1,372
  • 13
  • 20