在以下代码中 val_1 & val_2 返回相同的值。
val lst = List("abc","def","ghi", "jkl")
val indexes = List(1,2,3)
val val_1 = for (index:Int <- indexes) yield lst(index)
val val_2 = indexes.map(index => lst(index))
输出
val_1: List[String] = List(def, ghi, jkl)
val_2: List[String] = List(def, ghi, jkl)
如果地图可以做我们需要的,为什么需要收益? yield 还有其他用途吗?
答案 0 :(得分:2)
for (index:Int <- indexes) yield lst(index)
这是for comprehension。这个特殊的例子是使用它的最简单的形式。它相当于List.map
。
Scala的“for comprehension”等同于Haskell的“do”符号,它只不过是构成多个monadic操作的语法糖。
不同吗?
Scala的“for comprehension”是使用
组成多个操作的语法糖foreach
,map
,flatMap
,filter
或withFilter
为什么?
当你看到非常简单的理解时,地图/ foreach替代品看起来确实更好。但是,一旦开始编写它们,就很容易迷失在括号和嵌套级别中。当发生这种情况时,理解通常会更加清晰。
答案 1 :(得分:1)
使用for...yield
只是调用map的替代语法。我们可以通过使用-Xprint:parse
编译器标志编译代码来查看编译器如何去理解。
val lst = List("abc", "def", "ghi", "jkl");
val indexes = List(1, 2, 3);
val val_1 = indexes.withFilter(((check$ifrefutable$1) => check$ifrefutable$1: @scala.unchecked match {
case (index @ (_: Int)) => true
case _ => false
})).map(((index: Int) => lst(index)));
val val_2 = indexes.map(((index) => lst(index)));
正如您所看到的,您用于val_1的for
代码最终只是调用.map(((index: Int) => lst(index)))
,与val_2的代码相同。
withFilter部分归因于index:Int <- indexes
导致模式匹配,因为您在此声明索引必须是Int。如果我们删除类型注释以使该行只是val val_1 = for (index <- indexes) yield lst(index)
并重新编译,您将获得以下输出。
val lst = List("abc", "def", "ghi", "jkl");
val indexes = List(1, 2, 3);
val val_1 = indexes.map(((index) => lst(index)));
val val_2 = indexes.map(((index) => lst(index)));
现在很明显,for
和显式map
在编译后都是相同的。