为什么scala编译器不会将其识别为元组?

mus*_*oom 2 scala

如果我创建一个地图:

val m = Map((4, 3))
Run Code Online (Sandbox Code Playgroud)

并尝试添加新的键值对:

val m_prime = m + (1, 5)
Run Code Online (Sandbox Code Playgroud)

我明白了:

 error: type mismatch;
 found   : Int(1)
 required: (Int, ?)
       val m_prime = m + (1, 5)
Run Code Online (Sandbox Code Playgroud)

如果我做:

val m_prime = m + ((1, 5))
Run Code Online (Sandbox Code Playgroud)

要么:

val m_prime = m + (1 -> 5)
Run Code Online (Sandbox Code Playgroud)

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

我使用的是2.10.2

0__*_*0__ 5

这确实非常烦人(我经常遇到这种情况).首先,该+方法来自一般的集合特征,只采用一个参数 - 集合的元素类型.Map元素类型是一对(A, B).但是,Scala将括号解释为方法调用括号,而不是元组构造函数.解释见下一节.

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

val m_prime = m updated (1, 5)
Run Code Online (Sandbox Code Playgroud)

仍然不清楚为什么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.
Run Code Online (Sandbox Code Playgroud)

我的解释是,添加了可变参数版本,现在有歧义:是(a, b)一个Tuple2或两个参数列表ab(即使ab不类型的Tuple2,或许,编译器会开始寻找隐式转换).解决模糊性的唯一方法是使用上述三种方法中的任何一种.

  • 实际上,http://stackoverflow.com/a/18243932/1296806是一个更精确的演示.人们一直在问这个问题. (2认同)