Home > Software engineering >  Why is an error thrown when adding a tuple to a Map?
Why is an error thrown when adding a tuple to a Map?

Time:09-10

I don't understand why this works:

val romanNum = immutable.Map(1 -> "I", 2 -> "II", 3 -> "III", 4 -> "IV", 5 -> "V")
val romanNumWith10 = romanNum   (10 -> "X")

But this gives an error:

val romanNumWith10 = romanNum   (10, "X")

Both (10 -> "X") and (10, "X") return a Tuple2.

So both should work, but (10, "X") doesn't.

By the way, this works: val romanNumWith10 = romanNum ((10, "X"))

My Scala version is 3.1.2

It seems that Scala sees Int and String separately and not as a Tuple2, but why?

CodePudding user response:

Remember that Scala does not have operators, only methods and lots of sugar syntax.

// Thus, this:
val romanNumWith10 = romanNum   (10 -> "X")
// Desugars to:
val romanNumWith10 = romanNum. (10.->("X"))
// And since `10.->("X")` returns a tuple, then it works.

// Whereas, this:
val romanNumWith10 = romanNum   (10, "X")
// Desugars to:
val romanNumWith10 = romanNum. (10, "X")
// E.g. trying to call the ` ` method with two arguments; which is an error.

// Finally, this:
val romanNumWith10 = romanNum   ((10, "X"))
// Desugars to this:
val romanNumWith10 = romanNum. ((10, "X"))
// Which is again correct.

CodePudding user response:

I'm a bit suprised, it does not infer the right type not even in Scala 3. This dates back from Scala 2 as well. For example, in Scala 2.13.8:

val mymap             = Map(2 -> "w")
val x1: (Int, String) = (1, "x")

Doing:

  val mymap2 = mymap   x1 // ok

compiles but doing:

  val mymap3 = mymap   (1, "x") // type mismatch

does not.

FWIW, if a method receives a polymorphic argument, you will be tripped when using a tuple there too:

  def iCanConsumeAnything[T](x: T) = println(s"Consumed $x !")

Calling it with a tuple:

  iCanConsumeAnything(1, "x") // Consumed (1,x) !

compiles ok, as it treats (1, "x") as a tuple, and not as 2 arguments. But it would confuse anyone into thinking the method receives 2 arguments.

It's generally a bad practice to call the method like this, as well as adding tuple literals to a Map instead of using the special right arrow -> syntax.

  • Related