Given this Scala code:
object test {
def byval(a: Int) = println("Int")
def byval(a: Long) = println("Long")
def byname(a: => Int) = println("=> Int")
def byname(a: => Long) = println("=> Long")
def main(args: Array[String]) {
byval(5)
byname(5)
}
}
the call byval(5) compiles correctly, but byname fails to compile:
ambiguous reference to overloaded definition
Why? I would expect to observe the same behavior for by-value and by-name parameters with respect to overloading… How can it be fixed?
That's because JVM does not support a "by-name" parameter, so Scala has to implement it in another way. => X
actually compiles to a Function0[X]
, which erases to Function0[Object]
, which makes it impossible for Scala to distinguish two methods that differ only by the expected type of a by-name parameter.
Possible workaround without overloading (in addition to what has been said earlier), if you don't want to use different method names:
def byname[A](a: => A)(implicit manifest:Manifest[A]) =
manifest.erasure match {
case erasure if(erasure.isAssignableFrom(classOf[Long])) => println("=> Long")
case erasure if(erasure.isAssignableFrom(classOf[Int])) => println("=> Int")
}