Scala Operator Maps Precedence Gotcha

Published: 7 July, 2014

I ran into a unexpected operator precedence issue in Scala the other day with this code:

    val futureResponse = WS.url("http://query.yahooapis.com/v1/public/yql")
      .withHeaders("Accept" -> "application/json")
      .withQueryString(
        "q" -> "select * from yahoo.finance.quotes where symbol in (" + symbol + ")",
        "format" -> "json",
        "env" -> "store://datatables.org/alltableswithkeys",
      )
      .get()
    

The compiler complains about a type error "(String) found where (String, String) expected." Pretty obvious that the string concatenation + operators are breaking the Map tuples.

As it turns out, Scala's operator precedence is defined by the first character in the operator so Map's -> and String's + operators have the same precedence... so in other words, you can't use string concatenation in Maps (or any + or - operators) without surrounding them in parenthesis. (see this explanation operator precedence)

The issue is clearly demonstrated with this little example:

    scala> val x = Map("a" -> "one", "b" -> "two")
    x: scala.collection.immutable.Map[String,String] = Map(a -> one, b -> two)

    scala> val x = Map("a" -> "one" + "...", "b" -> "two")
    <console>:7: error: type mismatch;
    found   : String
    required: (?, ?)
    val x = Map("a" -> "one" + "...", "b" -> "two")
    ^

    scala> val x = Map("a" -> ("one" + "..."), "b" -> "two")
    x: scala.collection.immutable.Map[String,String] = Map(a -> one..., b -> two)
    

Comments