返回一个选项时,奇怪的行为mapValues(Strange behaviour in mapVal

2019-10-21 13:58发布

我已经下面定义的对象。 但我不明白为什么mapValues身体只有在test1的执行。 即。 为什么是输出:

调用TEST1

调用TEST2

制图:一

制图:两

映射:映射(1 - > XX,2 - > XX)

我有两个斯卡拉2.10和2.11相同的结果进行了测试。

object Test {

    def test1: Option[String] = {

        val map = Map(1 -> "One", 2 -> "Two")
        val mapped = map.mapValues { v =>
            println("Mapping: " + v)
            "Xx"
        }
        None
    }

    def test2: Option[String] = {

        val map = Map(1 -> "One", 2 -> "Two")
        val mapped = map.mapValues { v =>
            println("Mapping: " + v)
            "Xx"
        }
        println("Mapped: " + mapped)
        None
    }



    def main(args: Array[String]): Unit = {

        println("Calling test1")
        test1
        println("Calling test2")
        test2
    }

}

Answer 1:

对方的回答解释了这个问题,但作为一个解决方案,如果你想有一个严格的地图,只要使用普通的map

val m = Map(1 -> "One", 2 -> "Two")
val mapped = m.map { 
  case (k,v) => k -> {
    println("Mapping: " + v)
    "Xx"
  }
}

另外,您也可以定义自己的扩展方法做你想要什么:

import scala.collection.GenTraversableLike
import scala.collection.generic.CanBuildFrom
implicit class HasMapVals[T, U, Repr](val self: GenTraversableLike[(T, U), Repr]) extends AnyVal {
  def mapVals[R, That](f: U => R)(implicit bf: CanBuildFrom[Repr, (T, R), That]) = {
    self.map { case (k,v) => k -> f(v) }
  }
}

val m = Map(1 -> "One", 2 -> "Two")
val mapped = m.mapVals { v =>
  println("Mapping: " + v)
  "Xx"
}


Answer 2:

mapValues实际上返回一个视图 ,故结果懒惰地计算。 从scaladoc为mapValues

返回此映射的至f每个键(在此(密钥))映射的映射图。 将得到的地图包装了原始地图而不复制的任何元件。

因此,例如:

val mapped = Map(1 -> "One", 2 -> "Two").mapValues { v =>
    println("Mapping: " + v)
    "Xx"
}

在它自己的这个声明时将打印什么。 但是,一旦mapped被访问时,值将被计算,并且该语句将被打印。 (事实上,该值将被重新计算每次访问时间mapped

Test.test1 ,没有什么访问mapped ,因此它们的值永远不会计算。

Test.test2 ,你打印出mapped ,从而触发值的计算。



文章来源: Strange behaviour in mapValues when returning an option
标签: scala