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?
Why Scala compiler hasn't rather transformed the function literal to some kind of conceptual:
new (String, String) => String
Remember that Scala compiles down to JVM bytecode. There is no such thing as "conceptualnew (String, String) => String
" in JVM. There are only objects and methods (at least until Java 8). In Java language you have to use boring Callable<T>
, Runnable
or various Function
abstractions in Guava and Apache Commons. There is no way around it. From that perspective Scala basically hides Java boilerplate by adding syntactic sugar over anonymous FunctionX[...]
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).