This simple test, of course, works as expected:
scala> var b = 2 b: Int = 2 scala> b += 1 scala> b res3: Int = 3
Now I bring this into scope:
class A(var x: Int) { def +=(y:Int) { this.x += y } } implicit def int2A(i:Int) : A = new A(i)
I'm defining a new class and a += operation on it, and a convenient implicit conversion for those times when I want to add an Int to A's Int value.
I never expected this would affect the way my regular Int operations behave, when the "A" class is not at all part of the expression.
But it does:
scala> var b:Int = 0 b: Int = 0 scala> b += 1 scala> b res29: Int = 0 scala> b += 2 scala> b res31: Int = 0
What seems to be happening here is that the b:Int is implicitly converted to an "A", which is not bound to any variable, and then += is invoked on it, discarding the results.
Scala seems to give high precedence the implicit conversion over the natural += behavior (compiler magic, not an actual method) that is already defined to Ints. Common-sense as well as a C++ background tells me implicits should only be invoked as a last resort, when the compilation would otherwise fail. That leads to several questions...
Thanks
As others have noted, Int cannot have a += "method", because Int is immutable. What happens instead is that x += 1 is treated as a short form for x = x + 1, but only if there is no method called += that is defined on the type. So method resolution takes precedence.
Given that Scala lets you define += methods and also lets you do += on variables, could we have changed the priority of the two? I.e. try expanded += first and only if that fails search for a method named +=?
Theoretically yes, but I argue it would have been worse than the current scheme. Practically, no. There are many types in Scala's collection library that define both a + method for non-destructive addition and a += method for destructive addition. If we had switched the priority around then a call like
myHashTable += elem
would expand to
myHashTable = myHashTable + elem
So it would construct a new hashtable and assign this back to the variable, instead of simply updating an element. Not a wise thing to do...
From Programming in Scala, Chapter 17:
Whenever you write a += b, and a does not support a method named +=, Scala will try interpreting it as a = a + b.
The class Int does not contain method +=
. However class A
provides +=
method. That might be triggering the implicit conversion from Int
to A
.
I don't think it is a bug. Actually, Int only has a "+" method but doesn't have a "+=" method. b += 1 would transform to b = b + 1 in compile time if there is not a other implicit which has a "+=" method exists.
Scala seems to give high precedence the implicit conversion over the natural
+=
that is already defined toInt
s.
Which version of Scala are you talking about? I don't know of any version that has a +=
method on Int
. Certainly, none of the still supported versions do, that must be some really ancient version you have there.
And since there is no +=
on Int
, but you are calling a +=
method on Int
, Scala tries to satisfy that type constraint via an implicit conversion.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With