François Beausoleil
François Beausoleil

Reputation: 16515

Why is scalac complaining about method + on String?

Given the following Scala code:

def stream(callback: (String, Array[Byte]) => Unit) {
    callback("application/json;charset=utf-8", Array(1))
    callback("application/xml;charset=utf-8", Array(1))
}

@Test
def whenStreaming_thenShouldSeeSameMessages() {
    var actualMessages = List.empty[(String, Array[Byte])]
    sut.stream {
        (contentType, payload) =>
            actualMessages += (contentType, payload)
    }

    expect(List("application/json;charset=utf-8", "application/xml;charset=utf-8")) {
        actualMessages
    }
}

Why am I getting the following error message:

error: too many arguments for method +: (other: String)java.lang.String
actualMessages += (contentType, payload)

Specifically, payload is highlighted in IDEA, and on the command line, += is highlighted. I really don't understand that error message.

Upvotes: 2

Views: 193

Answers (1)

Kipton Barros
Kipton Barros

Reputation: 21112

The method to create a new list with an appended element is actually :+. To update the list var with an appended version, you need to do,

actualMessages :+= (contentType, payload)

Or you can prepend with,

actualMessages +:= (contentType, payload)
// or, equivalently,
// actualMessages ::= (contentType, payload)

(For big lists, prepending is actually preferable, as it's O(1) compared to O(n) for appending. One strategy is to use prepending to build the list in reverse, and then at the end call List.reverse.)

With the + operator you're trying to use, Scala thinks you want to do string concatenation,

scala> List("hello") + " world"
res0: java.lang.String = List(hello) world

This is an unfortunate carry-over from Java. Generic string concatenation is implemented in Scala using an implicit conversion defined in scala.Predef,

implicit def any2stringadd (x: Any): StringAdd 

What's happening is that List does not implement a + method, so the compiler looks for a conversion to something that does provide +, and finds any2stringadd. This is how, e.g., true + " false" works.

Upvotes: 6

Related Questions