tags:

views:

135

answers:

3

In the book "Programming in Scala" from Martin Odersky there is a simple example in the first chapter:

var capital = Map("US" -> "Washington", "France" -> "Paris")
capital += ("Japan" -> "Tokyo")

The second line can also be written as

capital = capital + ("Japan" -> "Tokyo")

I am curious about the += notation. In the class Map, I didn't found a += method. I was able to the same behaviour in an own example like

class Foo() {
    def +(value:String) = {
        println(value)
        this
    }
}

object Main {
  def main(args: Array[String]) = {
   var foo = new Foo()
   foo = foo + "bar"
   foo += "bar"
  }
}

I am questioning myself, why the += notation is possible. It doesn't work if the method in the class Foo is called test for example. This lead me to the prefix notation. Is the + a prefix notation for the assignment sign (=)? Can somebody explain this behaviour?

A: 

+= is an operator, where the default implementation uses the + operator. So in most cases, it already does exactly what you want.

Sjoerd
+8  A: 

If you have a symbolic method that returns the same object, then appending equals will perform the operation and assignment (as a handy shortcut for you). You may also always override the symbolic method. For example,

scala> class Q { def ~#~(q:Q) = this }
defined class Q

scala> var q = new Q
q: Q = Q@3d511e

scala> q ~#~= q
Rex Kerr
thanks a lot. With your answer I also learned that this works for more than one character (like ~#~).
Steve
+5  A: 
// Foo.scala
class Foo {
  def +(f: Foo) = this
}

object Foo {
  def main(args: Array[String]) {
    var f = new Foo
    f += f
  }
}

Output of scalac -print Foo.scala:

package <empty> {
  class Foo extends java.lang.Object with ScalaObject {
    def +(f: Foo): Foo = this;
    def this(): Foo = {
      Foo.super.this();
      ()
    }
  };
  final class Foo extends java.lang.Object with ScalaObject {
    def main(args: Array[java.lang.String]): Unit = {
      var f: Foo = new Foo();
      f = f.+(f)
    };
    def this(): object Foo = {
      Foo.super.this();
      ()
    }
  }
}

As you can see the compiler simply converts it to an assignment and a call of the method.

michael.kebe