理解中的选项

Options 有一个 flatMap 方法。这意味着它们可以用于理解。通过这种方式,我们可以解除常规功能,无需重新定义它们即可在 Option 上运行。

val firstOption: Option[Int] = Option(1)
val secondOption: Option[Int] = Option(2)

val myResult = for {
  firstValue <- firstOption
  secondValue <- secondOption
} yield firstValue + secondValue
// myResult: Option[Int] = Some(3)

当其中一个值是 None 时,计算的结束结果也将是 None

val firstOption: Option[Int] = Option(1)
val secondOption: Option[Int] = None

val myResult = for {
  firstValue <- firstOption
  secondValue <- secondOption
} yield firstValue + secondValue
// myResult: Option[Int] = None

注意:此模式更广泛地适用于名为 Monads 的概念。 (有关理解和 Monads 的页面应提供更多信息)

通常,为了便于理解,不可能混合不同的单子。但是由于 Option 可以轻松转换为 Iterable,我们可以通过调用 .toIterable 方法轻松混合 Options 和 Iterables。

val option: Option[Int] = Option(1)
val iterable: Iterable[Int] = Iterable(2, 3, 4, 5)

// does NOT compile since we cannot mix Monads in a for comprehension
// val myResult = for {
//   optionValue <- option
//   iterableValue <- iterable
//} yield optionValue + iterableValue

// It does compile when adding a .toIterable on the option
val myResult = for {
  optionValue <- option.toIterable
  iterableValue <- iterable
} yield optionValue + iterableValue
// myResult: Iterable[Int] = List(2, 3, 4, 5)

一个小注释:如果我们已经定义了我们的理解,那么围绕 for comprehension 的另一种方式会编译,因为我们的选项会被隐式转换。因此,始终添加此 .toIterable(或相应的功能取决于你使用的集合)以保持一致性非常有用。