scalafunctional-programming

Understanding function literal types


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?


Solution

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