Scala Map, ambiguity between tuple and function argument list
Asked Answered
H

3

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

So what's the deal with m += ("foo" , 2) not working? Scala gives the type error:

 error: type mismatch;
 found   : java.lang.String("foo")
 required: (String, Int)
       m += ("foo", 2)
             ^

Apparently Scala thinks that I am trying to call += with two arguments, instead of one tuple argument. Why? Isn't it unambiguous, since I am not using m.+= ?

Harappa answered 12/10, 2011 at 17:47 Comment(0)
C
10

Unfortunately a b (c, d, e, ..) desugars to a.b(c, d, e, ..). Hence the error.

Columbia answered 12/10, 2011 at 17:54 Comment(6)
In addition to that, here is a workaround m += ("foo" -> 2) or even m += "foo" -> 2.Heimlich
@Tempus: It desugars the way it does, because that's how the language works. Apropos the rationale for this decision, I remember there was some thread on [scala-user] discussing this issue. I am unable to find it at the moment. I will post the link if I manage to dig up that thread.Columbia
Can you cite formal Scala doc to support this? (Is this by design or is it considered a bug?)Harappa
@DanBurton: See Scala 2.9 language specification, page 85, first paragraph after the bullets at top.Columbia
@DanBurton: And yes, that's by design.Columbia
The corresponding reference for Scala 2.13 is at SLS 6.12.3 Infix OperatorsRalaigh
T
4

Isn't it unambiguous, since I am not using m.+= ?

No, it isn't, because parenthesis can always be used when there are multiple arguments. For example:

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

So you might ask, what multiple parameters? Well, the Scala API doc is your friend (or mine, at least), so I present you with:

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)

In other words, += takes a vararg.

Theadora answered 12/10, 2011 at 21:21 Comment(1)
The freedom to add a space before the open paren of arguments irritates me >,<Harappa
M
3

The preferred way to define map entries is to use the -> method. Like

m += ("foo" -> 2)

Which constructs a tuple. a -> b gets desugared to a.->(b). Every object in scala has a -> method.

Motorist answered 12/10, 2011 at 18:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.