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);
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添加到代码中。
for-comprehension只是对flatMap、map和filter的语法糖,你的代码相当于。
val option1 = Some(1)
val option2 = Some(2)
val sumOptions = option1.flatMap { i =>
option2.map { j =>
i + j
}
}