0

Here's some code which looks reasonable enough to me:

val myMap: Map[Int, Int] = ((x: Int) => Map[Int, Int](1 -> x + 1, 2 -> x + 2))(4)

When I try to compile it, I get two errors like this:

Error:(20, 68) type mismatch;
 found   : Int(1)
 required: String
    val myMap: Map[Int, Int] = ((x: Int) => Map[Int, Int](1 -> x + 1, 2 -> x + 2))(4)
                                                                   ^

I understand that my compiler is trying to use the string addition implementation of +. But why is it doing that? How do I ask the compiler to use integer addition here?

(Changing Int to Integer doesn't help.)

Buck Shlegeris
  • 517
  • 6
  • 22

3 Answers3

5

Here is a simpler example that reproduces the error:

scala> def fail(x: Int) = 1 -> x + 1
<console>:10: error: type mismatch;
 found   : Int(1)
 required: String
       def fail(x: Int) = 1 -> x + 1
                                   ^

All of the operators in play are left-associative, so everything reads left-to-right. That is, the call chain looks like this:

1.->(x).+(1)

or using infix notation:

(1 -> x) + 1

1 -> x returns a tuple (1, x) and a tuple does not have a + method, so the compiler attempts to implicitly convert it to a String via toString, because String does have a + method, which eventually fails because Int is required.

Just use parentheses to group things appropriately:

scala> def foo(x: Int) = 1 -> (x + 1)
foo: (x: Int)(Int, Int)
Michael Zajac
  • 55,144
  • 7
  • 113
  • 138
1

'->' has the same precedence as '+', so 1 -> x + 1 parses as (1 -> x) + 1. Adding parentheses as 1 -> (x + 1) fixes this error.

Community
  • 1
  • 1
Bakkot
  • 1,175
  • 7
  • 13
0

The problem is that according to Scala's precedence rules, -> binds as tightly as +, because it starts with -.

It's fixed by adding parentheses:

val myMap: Map[Int, Int] = ((x: Int) => Map[Int, Int](1 -> (x + 1), 2 -> (x + 2)))(4)
Community
  • 1
  • 1
Buck Shlegeris
  • 517
  • 6
  • 22