如果`for`中的至少一个要素为None

时间:2019-05-14 20:16:37

标签: scala flatmap for-comprehension

我很难理解Scala中使用for-compression的机制。 例如,如果我有

val x = for {
  i <- Option(1)
  j <- Option(2)
  k <- Option(3)
} yield (i,j,k)

xx: Option[(Int, Int, Int)] = Some((1,2,3))。 但是,例如,如果组件中的至少一个为“无”,则

val x = for {
  i <- Option(1)
  j <- Option(2)
  k <- None
} yield (i,j,k)

然后xx: Option[(Int, Int, Nothing)] = None,而我实际上希望看到的是:x: Option[(Int, Int, Nothing)] = Some((1,2,None))

我检查了FAQ from Scala official documentation,其中明确指出for-comprehensionflatmapmap的组合。但是我仍然很难理解xNone

我认为我错过了一些关于flatmapmap区别的重要概念。

1 个答案:

答案 0 :(得分:5)

第一个具有理解力的“减糖”:

val x = Option(1).flatMap(
  i => Option(2).flatMap(
    j => Option(3).map(
      k => (i, j, k)
    )
  )
)

如您所见-第一个Option使用获取其值(如果存在)并返回3元组(使用第二个Option的类似操作)的函数进行平面映射。无论该函数是什么-整个表达式的形式均为:

val x = Option(1).flatMap(f)

现在,如果我们将Option(1)替换为None(就像您在第二个表达式中所做的那样),我们显然会得到None

val x = None.flatMap(f) // None, for any f

您期望的结果(Some((None, 2, 3))不太有用-因为对于不同的输入它会有不同类型:会是(Option[Int], Int, Int)吗?还是(Int, Int, Int)?还是(Option[Int], Option[Int], Option[Int])?实际上,(None, 2, 3)(1, None, 3)(1, 2, None)的唯一常见类型是不太有用的(Any, Any, Any)