2

如果我创建地图:

val m = Map((4, 3))

并尝试添加一个新的键值对:

val m_prime = m + (1, 5)

我得到:

 error: type mismatch;
 found   : Int(1)
 required: (Int, ?)
       val m_prime = m + (1, 5)

如果我做:

val m_prime = m + ((1, 5))

或者:

val m_prime = m + (1 -> 5)

然后它工作。为什么编译器不接受第一个示例?

我正在使用 2.10.2

4

1 回答 1

5

这确实很烦人(我经常遇到这种情况)。首先,该+方法来自一个通用的集合特征,只接受一个参数——集合的元素类型。Map的元素类型是对(A, B)。但是,Scala 将此处的括号解释为方法调用括号,而不是元组构造函数。解释在下一节中显示。

为了解决这个问题,您可以避免元组语法并使用箭头关联key -> value,或者使用双括号,或者使用updated特定于Map. updated做同样的事情,+但将 key 和 value 作为单独的参数:

val m_prime = m updated (1, 5)

仍然不清楚为什么 Scala 会在这里失败,因为通常中缀语法应该可以工作并且不需要括号。由于方法重载,这种特殊情况似乎被打破了:有第二种+方法采用可变数量的元组参数。

示范:

trait Foo {
  def +(tup: (Int, Int)): Foo
}

def test1(f: Foo) = f + (1, 2)  // yes, it works!

trait Baz extends Foo {
  def +(tups: (Int, Int)*): Foo // overloaded
}

def test2(b: Baz) = b + (1, 2)  // boom. we broke it.

我的解释是,添加了 vararg 版本后,现在存在歧义:是(a, b)一个Tuple2或两个参数的列表aand b(即使aandb不是 type Tuple2,也许编译器会开始寻找隐式转换)。解决歧义的唯一方法是使用上述三种方法中的任何一种。

于 2013-08-17T20:47:00.930 回答