Scala Map,元组和函数参数列表之间的歧义问题

8
val m = scala.collection.mutable.Map[String, Int]()
// this doesn't work
m += ("foo", 2)
// this does work
m += (("foo", 2))
// this works too
val barpair = ("bar", 3)
m += barpair

那么 m += ("foo", 2) 为什么不能正常工作呢?Scala 报错类型如下:
 error: type mismatch;
 found   : java.lang.String("foo")
 required: (String, Int)
       m += ("foo", 2)
             ^

显然,Scala认为我正在尝试使用两个参数调用+=,而不是一个元组参数。为什么?这不明显吗,因为我没有使用m.+=吗?
3个回答

10

很遗憾,a b (c, d, e, ..)会被转化为a.b(c, d, e, ..),这就是错误的原因。


7
除此之外,这里有一个变通方法:使用 m += ("foo" -> 2) 或者 m += "foo" -> 2。原文的意思是,在一个名为“m”的程序中,通过添加键值对“foo”和“2”来解决某个问题。 - agilesteel
@Tempus:它以这种方式进行解糖,因为这就是语言的工作方式。关于这个决定的理由,我记得在[scala-user]上有一些讨论这个问题的帖子。我现在找不到它。如果我成功挖掘出那个帖子,我会发布链接的。 - missingfaktor
你能引用正式的Scala文档来支持这个吗? (这是设计意图还是被认为是错误?) - Dan Burton
3
@DanBurton: 参见Scala 2.9语言规范,第85页,在顶部项目符号后的第一个段落。 - missingfaktor
@DanBurton:是的,这是有意设计的。 - missingfaktor
1
Scala 2.13 的相应参考文献位于 SLS 6.12.3 中缀操作符 - Mario Galic

4

因为我没有使用m.+=,所以这不是歧义的吗?

不是的,因为当存在多个参数时,可以始终使用括号。例如:

List(1, 2, 3) mkString ("<", ", ", ">")

那么你可能会问,什么是多个参数?好的,Scala API文档是你的朋友(至少是我的),所以我给你介绍:

scala> val m = scala.collection.mutable.Map[String, Int]()
m: scala.collection.mutable.Map[String,Int] = Map()

scala> m += (("foo", 2), ("bar", 3))
res0: m.type = Map(bar -> 3, foo -> 2)

换句话说,+= 接收可变参数。

在参数的左括号前添加一个空格的自由让我感到很恼火 >,< - Dan Burton

3
首选定义地图条目的方法是使用 -> 方法。就像下面这样:
m += ("foo" -> 2)

构建元组。a -> b 被转换为 a.->(b)。Scala中的每个对象都有一个 -> 方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接