According to the debugger, in the following snippet scala is boxing and unboxing the Char
argument and later boxing and unboxing the Boolean
result. Why? How to avoid that?
object Test{
def user(predicate: Char => Boolean): Boolean = {
predicate('3')
}
def main(args: Array[String]): Unit = {
var b0 = false;
for( i <- 1 to 100 ) { // warm up
b0 ||= user(Character.isDefined)
}
println(b0)
// start debugging here
val b1 = user(Character.isDigit);
println(b1)
val b2 = user(c => c == 'a');
println(b2)
}
}
As far as I know, the boxing/unboxing is expected when the involved parameters or return type is parameterized. But this is not the case. <= Wrong
Scala version 2.13.3
user
takes an argument of type Char => Boolean
, which is syntactic sugar for Function1[Char, Boolean]
. Function1
is a generic trait from the Scala standard library, and because generics are implemented with erasure on the JVM, the type Char
is erased to java.lang.Object
at runtime. Thus, the Char
needs to be boxed when passing it to the function.
To avoid this, you can define your own trait:
trait CharPredicate {
def apply(c: Char): Boolean
}
Because this trait isn't generic, no type erasure and hence no boxing 🥊 is going to take place. You will still be able to use function literal syntax, because Scala allows that for all traits with a single abstract method.