Assuming this code:
def main(args: Array[String]) {
val func = (x: String, y :String) => x + ", " + y
println(myFunc(func))
}
def myFunc(f: (String, String) => String) = {
f("Hey","how are you?")
}
The second line of this code is replaced by compiler to:
val func = new Function2[String, String, String] {
def apply(x: String, y: String): String = x + ", " + y
}
I can deduce that func type in this case corresponds also to (String, String) => String) type, as the myFunc signature shows; meaning that Function2[String, String, String] is the same type as (String, String) => String.
Why different notations? Why Scala compiler hasn’t rather transformed the function literal to some kind of conceptual: new ((String, String) => String) without boring with Function2[String, String, String] type? Or vice versa.
One explanation would be that a class name cannot be multipart as: (T1, T2) => R.
But why not after all?
Remember that Scala compiles down to JVM bytecode. There is no such thing as “conceptual
new (String, String) => String” in JVM. There are only objects and methods (at least until Java 8). In Java language you have to use boringCallable<T>,Runnableor variousFunctionabstractions in Guava and Apache Commons. There is no way around it. From that perspective Scala basically hides Java boilerplate by adding syntactic sugar over anonymousFunctionX[...]classes.That’s also one of the reasons why Scala compiler has to do so much fiddling when you use a method where function was expected (so called eta expansion).