I’ve found extremely weird behaviour (scala 2.9.1 ) using and defining implicit values, and wondering if anyone can explain it, or if it’s a scala bug?
I’ve created a self contained example:
object AnnoyingObjectForNoPurpose {
trait Printer[T] {
def doPrint(v: T): Unit
}
def print[T : Printer](v: T) = implicitly[Printer[T]].doPrint(v)
trait DelayedRunner extends DelayedInit {
def delayedInit(x: => Unit){ x }
}
// this works, as it should
object Normal extends DelayedRunner {
implicit val imp = new Printer[Int] {
def doPrint(v: Int) = println(v + " should work")
}
print(343)
}
// this compiles, but it shouldn't
// and won't run, cause the implicit is still null
object FalsePositive extends DelayedRunner {
print(123)
implicit val imp = new Printer[Int] {
def doPrint(v: Int) = println(v + " should not compile")
}
}
def main(args: Array[String]) {
implicit val imp = new Printer[Int] {
def doPrint(v: Int) = println(v + " should work")
}
print(44)
// print(33.0) // correctly doesn't work
Normal // force it to run
FalsePositive // force this to run too
}
}
Suppose you changed your definition of
delayInitto be a no-op, i.e.Then in your main method do something like
As expected that will print
FP.imp: null, but the real point of the exercise is to illustrate that the block that defines the body ofFalsePositiveis acting like a regular class body, not a function body. It’s defining public members when it seesval, not local variables.If you added a method to
AnnoyingObjectForNoPurposelike the following, it wouldn’t compile becauseprint‘s implicit requirement isn’t satisfied.However if you defined a class along the same principle, it would compile, but fail at runtime when initialized, just like your
FalsePositiveexample.To be clear, the compile behavior of
Finehas nothing to do with the presence of theimplicit. Class/object initializers are very happy to compile withvalinitializers which reference undefinedvals.Boringcompiles just fine and when it is referenced, it printsa=1 b=0It seems like your question boils down to “Should the body of a class/object deriving from
DelayedInitbe compiled as if it’s a class body or a function block?”It looks like Odersky picked the former, but you’re hoping for the latter.