奇怪的...

    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 说默认必须是类型:=> B

如果我理解正确,在这种情况下,一个无参数函数返回一个 Int。
  • 为什么采用 mydefault1 的示例可以编译,因为它需要一个参数,所以符合规范?
  • 为什么返回函数,而不是调用函数来产生默认值?显然,类型安全已被破坏,因为 getOrElse 必须返回一个 Int,而不是一个函数。 (如果我误解了文档并错误地提供了一个需要 Int 值的函数,为什么编译器让我提供一个函数,而不是一个 Int?)。

  • 编辑

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

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

    这可能吗?

    最佳答案

    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,它必须是 map 的值类型Int和默认值的类型的通用父类(super class)型。默认值的类型是Function0。如果分配结果,则会看到父类(super class)型为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!!
    

    10-07 19:32
    查看更多