object any2stringadd
trait Adder[A] {
def add(s: A, i: Int): A
}
case class MyTest(i: Int)
implicit val myAddable: Adder[MyTest] = new Adder[MyTest] {
def add(s: MyTest, i: Int) = MyTest(s.i + i)
}
implicit final class Ops[A](val lhs: A)(implicit adder: Adder[A]) {
def +[B](i: B)(implicit n: Numeric[B]) = {
adder.add(lhs, n.toInt(i))
}
def add[B](i: B)(implicit n: Numeric[B]) = {
adder.add(lhs, n.toInt(i))
}
}
val a = MyTest(2)
a.add(5)
a + 5
I only added the first line.
So the reason it didn’t work is that there is an implicit conversion any2stringadd which adds a + method to Any. When the compiler now looks for a + method it finds your implicit conversion andany2stringadd, doesn’t know which to choose and compilation fails.
The reason my code worked is that my any2stringadd shadows Predef.any2stringadd so it is no longer eligible as an implicit conversion.
Hmm. In one way: “Clever” In other ways: “Why???” Btw IntelliJ has 0 idea what happens, but the code compiles as expected
I started to refactor a codebase which transforms an inner ADT structure to languages, and I didn’t want to break hardly the already existing code, I think this will work as a minimal effort refactor, and I hope nobody uses “+” and “-” between those things.
Basically, any2stringadd seemed like a good idea at the time, back in the early days of the language, since being able to concatenate anything to a String was convenient for building complex Strings. But in the years since, we’ve gained string interpolation (generally a better way to do it), and this has proven to be a frequently inconvenient misfeature.
I think there’s a fair consensus that it’s more trouble than it’s worth. Personally, I’m hoping it goes away in Scala 3.
Note that any2stringadd is formally deprecated in Scala 2.13:
scala 2.13.0> (new AnyRef) + "foo"
^
warning: method any2stringadd in object Predef is deprecated (since 2.13.0): Implicit injection of + is deprecated. Convert to String to call +
res1: String = java.lang.Object@24e83d19foo
scala 2.13.0> 3 + "foo"
^
warning: method + in class Int is deprecated (since 2.13.0): Adding a number and a String is deprecated. Use the string interpolation `s"$num$str"`
res0: String = 3foo