I was playing with implicits but I got some behaviour that I don't understand.
I defined a simple class and its companion object (just to make a quick test on implicits) as follows
class SimpleNumber(val numb: Int) {
def sum(n: Int) = numb + n
}
object SimpleNumber {
implicit def stringToInt(s: String) = s.toInt
}
The method stringToInt
is supposed to work in the event I call the sum method by passing a string instead of an int, so that it can be converted to an int (it's just for testing purposes, so I don't need to check errors or exceptions).
If I paste the above code in the repl (:paste), I get this warning
warning: implicit conversion method stringToInt should be enabled by making the implicit value scala.language.implicitConversions visible. This can be achieved by adding the import clause 'import scala.language.implicitConversions' or by setting the compiler option -language:implicitConversions.
So I moved to VSCode and pasted in the same code, to see if I could get some more info via metals plugin, but that warning doesn't even pop out. Then I created a new object that extends the App trait to test the code like this
object TestDriver extends App{
val a = new SimpleNumber(4)
println(a.sum("5"))
}
but I received the following error
type mismatch; found : String("5") required: Int
I tried importing the implicitConversions as the repl suggested, first in the companion object and then in the TestDriver object, but to no avail. Then I imported the implicit method directly in the TestDriver object, and that worked.
import SimpleNumber.stringToInt
object TestDriver extends App{
val a = new SimpleNumber(4)
println(a.sum("5"))
}
Why doesn't the import scala.language.implicitConversions
work as I thought it would? I'm using scala 2.13.3
a.sum("5")
the compiler will try to search for an implicit conversion (which, btw, are discouraged) on the current lexical scope, or in the companion object of the source and target types (Int and String respectively) and neither of those has such implicit. You can, however,import SimpleNumber._
before so the conversion is put into the lexical scope, but that is not what you want. TL;DR; theSimpleNumber
object is not in scope. – Luis Miguel Mejía SuárezSimpleObject
is not in scope, and how to bring in scope – RevjeSimpleObject
is not in the implicit scope of a transformation of an Int into a String, why? because that is what the spec says (but the rationale is simple, the implicit scope can not be too big because the compiler would be slower). You can bring its implicit members into scope the same way you can bring anything into scope, by explicitly importing it. The rule of companions objects being in the implicit scope is for source and target types, for example, if you rather had a conversion from SimpleObject into String or vice-versa it would have worked – Luis Miguel Mejía Suárez