The following does not compile:
package play
object Stats2 {
def variance(data: Seq[Double], dof: Int = 0): Double = {
println("variance Double direct"); 1.0
}
def variance[T](data:Seq[T], dof: Int = 0)(implicit ex: T => Double): Double = {
println("variance Double extracted"); 1.0
}
}
The compiler says:
$ scalac erasure2.scala
erasure2.scala:7: error: double definition:
method variance$default$2:[T]=> Int and
method variance$default$2:=> Int at line 4
have same type after erasure: ()Int
def variance[T](data:Seq[T], dof: Int = 0)(implicit ex: T => Double): Double = {
^
one error found
If dof :Int = 0 is changed to dof: Int, the example compiles and works as expected.
It seems ugly that the presence or absence of a default parameter value changes whether the code is valid or not.
What is the explanation for why this really makes sense?
The problem is that when you use default arguments, its name and the method name is used to generate a static attribute, this way: [methodName]$default$[argumentPosition]
, in your case it will be variance$default$2
, so if both have default arguments, the compiler will try to generate 2 static attributes with the same name.
if the type of the other arguments in the method were used, this could be avoided. You may submit a SIP Proposal to change this behaviour in the compiler.
You can read more about this on this post
If you want to check by yourself, try compiling your object with each method and inspect the class using javap [XXX]
, where is the name of the object or class, in your case javap Stats2
.
Your first method will give:
public final class Stats2 extends java.lang.Object{
public static final int variance$default$2();
public static final double variance(scala.collection.Seq, int);
}
and your second method will give:
public final class Stats2 extends java.lang.Object{
public static final int variance$default$2();
public static final double variance(scala.collection.Seq, int, scala.Function1);
}
finally, by removing the default value for dof in the second method, we get:
public final class Stats2 extends java.lang.Object{
public static final double variance(scala.collection.Seq, int, scala.Function1);
}
So the static final int variance$default$2()
is what is making the compilation to fail, which is generated by the default value.
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