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

时间:2013-12-23 21:07:51

标签: scala

...奇

    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>

docs表示默认值必须为:=&gt;乙

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

  1. 为什么采用mydefault1编译的示例,因为它需要一个参数,所以符合规范?

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

  3. 修改

    显然:

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

    还让一个函数用于指定默认值。我想要的是能够使用在执行查找时提供的函数覆盖默认值(即函数可能在地图的生命周期内发生变化)

    这可能吗?

1 个答案:

答案 0 :(得分:15)

The definition of 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()调用。形式上,该参数被定义为call-by-name参数。


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

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!!
相关问题