Scala对地图的收益有什么用?

时间:2018-05-17 18:51:18

标签: scala scala-collections

在以下代码中 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 还有其他用途吗?

2 个答案:

答案 0 :(得分:2)

for (index:Int <- indexes) yield lst(index)

这是for comprehension。这个特殊的例子是使用它的最简单的形式。它相当于List.map

根据FAQ/yield

  

Scala的“for comprehension”等同于Haskell的“do”符号,它只不过是构成多个monadic操作的语法糖。

不同吗?

  

Scala的“for comprehension”是使用foreachmapflatMapfilterwithFilter

组成多个操作的语法糖

为什么?

  

当你看到非常简单的理解时,地图/ 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在编译后都是相同的。