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

scala Map.getOrElse-如何为默认值提供函数,scala,Scala,奇怪的 val h=new HashMap[Long,Int]() def mydefault0():Int=101 println(h.getOrElse(99,default=mydefault0 ))//打印 def mydefault1(键:长):Int=102 println(h.getOrElse(98,default=mydefault1 ))//打印 默认值必须是类型:=>B 如果我理解正确,在本例中,no arg函数返回Int 为什么使用mydefault1的示例会编译,因为

奇怪的

val h=new HashMap[Long,Int]()
def mydefault0():Int=101
println(h.getOrElse(99,default=mydefault0 ))//打印
def mydefault1(键:长):Int=102
println(h.getOrElse(98,default=mydefault1 ))//打印
默认值必须是类型:=>B

如果我理解正确,在本例中,no arg函数返回Int

  • 为什么使用mydefault1的示例会编译,因为它需要一个参数,因此符合规范

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

  • 编辑

    显然:

    • 扩展HashMap并覆盖默认值,或
    • 使用HashMap.withDefault
    还可以使用函数来指定默认值。我希望能够使用在执行查找时提供的函数覆盖默认值(即,该函数可能在映射的生命周期内更改)

    这可能吗?

    default
    参数不采用将是
    ()=>B1
    的函数,而是采用类型为
    B1
    的延迟访问值。这种无参数的“函数”B1有时也称为thunk。正确的使用方法如下:

    getOrElse[B1 >: B](key: A, default: => B1): B1
    
    那么您在使用mydefault0时看到了什么?显然,返回值的类型为
    B1
    ,它必须是映射值类型
    Int
    和默认值类型的公共超类型。默认值的类型为
    Function0
    。如果指定结果,则会看到超类型为
    Any

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

    谢谢,这就澄清了我的错误。但回到问题上来。。。所以,假设我想要一个Map[String,Array[Int]],我就不能在缺少键时使用getOrElse来构造一个新的默认数组,对吗?这将导致每个值都是相同的对象。换句话说,没有提供在每次查找时生成默认值的函数的规定(覆盖HashMap的默认值,或者使用Map.withDefault不允许我在进行查找时指定默认生成器)。正确理解按名称参数是什么以及它们的行为方式非常重要(以及为什么它们不是“懒惰的”)。关于按名称参数,需要知道的最重要的事情是,被调用的方法确定实际参数表达式的求值次数,这可能是0、1或更多次。懒惰参数只求值0或1次。谢谢——现在一切都讲得通了。
    import collection.mutable
    
    val h = new mutable.HashMap[Long, Int]()
    
    def mydefault0(): Int = 101
    
    println(h.getOrElse(99, default = mydefault0()))
    
    val x = h.getOrElse(99, default = mydefault0 _ )  // x: Any = <function0>
    
    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!!