我遇到了 Scala 的一个奇怪的功能,其中以下两个不等价:
var map = Map[A,B]()
map += ( key -> (valueGen(key)))
没有给出相同的结果
var map = Map[A,B]()
val result = valueGen(key)
map += ( key -> result)
第二个片段执行您期望的操作,而第一个片段没有正确添加到地图中,而是覆盖了以前的值,以便地图只包含最近写入的值,而不是添加到其中的所有值。
我遇到了 Scala 的一个奇怪的功能,其中以下两个不等价:
var map = Map[A,B]()
map += ( key -> (valueGen(key)))
没有给出相同的结果
var map = Map[A,B]()
val result = valueGen(key)
map += ( key -> result)
第二个片段执行您期望的操作,而第一个片段没有正确添加到地图中,而是覆盖了以前的值,以便地图只包含最近写入的值,而不是添加到其中的所有值。
我以前见过这个,只有当valueGen
函数和这段代码一起递归时才会导致问题。我相信这是因为括号中的表达式不能保证首先执行。括号仅绑定运算符。Scala 必须像这样解释地图上的 +=:
map = map + (expression)
当它执行时map + (expression)
,它首先将映射操作数读取到加号运算符并保存。然后它尝试评估(expression)
. 在(expression)
包含对该valueGen
函数的调用的情况下,它会进行调用,然后将其添加到此特定调用的缓存映射中。如果调用valueGen
最终递归并调用此函数(并首先修改地图),这将使用此调用的缓存版本+结果覆盖这些更改。这就是为什么如果您的函数是递归的,您希望将valueGen
函数与 += 运算符分开调用。
当我跑
object test {
def main(args: Array[String]) {
var map = Map[String,Int]()
map += ("hello" -> (valueGen("hello")))
map += ("bye" -> (valueGen("bye")))
println(map)
}
def valueGen(x: String) = x.length
}
我明白了
Map(hello -> 5, bye -> 3)
您能否提供一个可运行的示例来说明您所看到的内容?