Search code examples
scalaboxingunboxing

Scala is boxing and unboxing non parametric function arguments and result. Why? Posible duplicate


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


Solution

  • 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.