scala Map.getOrElse-如何为默认值提供函数



奇数。。。

val h = new HashMap[Long, Int]()
def mydefault0():Int = 101
println( h.getOrElse(99, default=mydefault0 _ ) )  // Prints <function0>
def mydefault1(key:Long):Int = 102
println( h.getOrElse(98, default=mydefault1 _ ) )  // Prints <function1>

文件说默认类型必须是:=>B

如果我理解正确的话,在这种情况下,一个无arg函数返回一个Int。

  1. 为什么以mydefault1为例进行编译,因为它需要一个参数,因此符合规范?

  2. 为什么要返回函数,而不是调用函数来生成默认值?显然,类型安全性已经被破坏,因为getOrElse必须返回Int,而不是函数。(如果我误解了文档,错误地提供了一个需要Int值的函数,为什么编译器让我提供一个函数,而不是Int?)。

编辑

清楚:

  • 扩展HashMap并覆盖默认值,或者
  • 使用HashMap.withDefault

还允许使用函数来指定默认值。我想要的是能够用在执行查找时提供的功能覆盖默认值(即,该功能可能在地图的使用寿命内发生变化)

这可能吗?

getOrElse:的定义

getOrElse[B1 >: B](key: A, default: => B1): B1

default参数不是接受一个函数——它应该是() => B1,而是一个类型为B1的延迟访问值。这个无参数的"函数"=> B1有时也被称为thunk。正确的使用方法如下:

import collection.mutable
val h = new mutable.HashMap[Long, Int]()
def mydefault0(): Int = 101
println(h.getOrElse(99, default = mydefault0()))

那么你在mydefault0 _上看到了什么呢?显然,返回值的类型为B1,它必须是映射的值类型Int和默认值类型的公共超类型。默认值的类型为Function0。如果分配结果,您会看到超类型是Any:

val x = h.getOrElse(99, default = mydefault0 _ )  // x: Any = <function0>

因此,错误在于假设您必须传入一个函数,而实际上您正在声明一个延迟求值的表达式。只有在需要默认值时才会调用调用mydefault0()。从形式上讲,参数被定义为按名称调用参数。


编辑:关于您的评论。按名称调用意味着您每次获得一个新数组。

val m = Map("foo" -> Array(1, 2, 3))
def myDefault = {
println("called-default")
Array(4, 5, 6)
}
val a1 = m.getOrElse("foo", myDefault)  // myDefault not called
val a2 = m.getOrElse("bar", myDefault)  // myDefault called
val a3 = m.getOrElse("baz", myDefault)  // myDefault called
a2 == a3  // false!!

最新更新