为什么在foryield表达式中,两个Some[Int]可以相加?

问题描述 投票:0回答:1
val listSomeInt: List[Some[Int]] = List(Some(1),Some(2))
// Some(1) + Some(2) will not compile of course

问题1:为什么在foryield表达式中,同样的求和计算也可以?

val sumSomeInt = for{
    i1<- listSomeInt(0)
    i2<- listSomeInt(1)
} yield i1 + i2
println(sumSomeInt) // Some(3)

问题2:如何在 "for{}"中println(i1.getClass)或其他方法来查看i1的类型?反编译可能会给出一些提示,但不是那么透彻地理解(对我来说)。

private final List<Some<Object>> listSomeInt = …;
public List<Some<Object>> listSomeInt() { return this.listSomeInt; }
public Option<Object> sumSomeInt() { return this.sumSomeInt;  }
private final Option<Object> sumSomeInt = (Option)listSomeInt().apply(0)).flatMap(this::$anonfun$sumSomeInt$1$adapted);
scala for-loop option
1个回答
4
投票

This.SomeInt =..:

for{
    i1<- listSomeInt(0)
    i2<- listSomeInt(1)
} yield i1 + i2

是这个的语法糖。

listSomeInt(0).flatMap { i1 =>
  listSomeInt(1).map { i2 =>
    i1 + i2
  }
}

这等于:

Option(1).flatMap { i1 =>
  Option(2).map { i2 =>
    i1 + i2
  }
}

你可以进一步解释为:

Option(1).map { i1: Int => // i1 == 1 in this example
  Option(2).map { i2: Int => // i2 == 2 in this example
    i1 + i2 // i1 + i2 == 3 in this example
  } // Option[Int] == Some(3)
} // Option[Option[Int]] == Some(Some(3))
.flatten // Option[Int] == Some(3)

你可以预览很多这样的东西,如果你会使用像 ammonite 这样的 REPL 来测试部分结果。

@ Option(1).map(i => i *2)
res9: Option[Int] = Some(2)

@ Option(1).map(i => Option(i * 2))
res10: Option[Option[Int]] = Some(Some(2))

@ Option(1).map(i => Option(i * 2)).flatten
res11: Option[Int] = Some(2)

@ Option(1).flatMap(i => Option(i * 2))
res12: Option[Int] = Some(2)

@ Option(1).map(i => Option(2).map(j => i + j)).flatten
res13: Option[Int] = Some(3)

@ Option(1).flatMap(i => Option(2).map(j => i + j))
res14: Option[Int] = Some(3)

好的IDE(如IntelliJ)也能够将类型的add添加到代码中。


1
投票

for-comprehension只是对flatMap、map和filter的语法糖,你的代码相当于。

 val option1 = Some(1)
 val option2 = Some(2)
 val sumOptions = option1.flatMap { i =>
      option2.map { j =>
        i + j
      }
    }
© www.soinside.com 2019 - 2024. All rights reserved.