Readability
Verbose version is very clear for Java
-developers. It looks almost like an anonymous class in Java. So it could be used to explain lambdas. This is the only advantage of the verbose version.
REPL support
There is a little difference in REPL, but it's not something useful:
scala> new Function2[Double, Double, Double] {
| def apply(t1: Double, t2: Double): Double = t1 + t2;
| }
res0: java.lang.Object with (Double, Double) => Double = <function2>
scala> val sum: (Double, Double) => Double = _ + _
sum: (Double, Double) => Double = <function2>
Bytecode size
In terms of jvm
trait is an interface. When you create a class based on trait compiler generates methods with simple call of implementation from trait's companion object.
FunctionN
traits up to two parameters are specialized
on Int
, Long
and Double
parameters, the result type parameter is additionally specialized on Unit
, Float
and Boolean
. It means for Function2
you'll get 54 addition apply
methods (named like apply$mcZDD$sp
).
With lambda version you are using abstract class scala.runtime.AbstractFunction2
. All methods are generated in this class. Overridden only those that are necessary. Class-file size for lambda (ClassName$anonfun$1.class
) is 1012 bytes. Less than 1kB.
In case of new Function2
all methods are generated in anonymous class. Class-file size for anonymous class (ClassName$anon$1.class
) is about 20 kB.
For Function3
(not specialized) difference is not so big: 1.1kB
vs 1.7kB
, but FunctionN
with 0-2 arguments are the most common lambdas. Without AbstractFunctionN
bytecode size would be huge.