Experiment with passing Scala methods as function parameters, signature overloading

As a brief note to self, I was experimenting with passing methods as parameters to Scala functions — in particular trying to overload those method signatures to see what would work and what would not work — and I came up with these simple function signature overloading tests:

object Test extends App {

    // overload `exec` to take Function1, Function2, and Function3
    def exec(f: () => Int): Int = 1
    def exec(f: (String) => Int): Int = 2
    //def exec(f: (Int) => Int): Int = 3
    def exec(f: (String, Int) => Int): Int = 3

    //def oneM() = 1
    //println( exec(oneM) )

    // WORKS
    def twoM(s: String): Int = 2
    println( "twoM: " + exec(twoM _) )
    println( "twoM: " + exec(twoM(_)) )

    def threeM(s: String, i: Int): Int = 3
    println( "threeM: " + exec(threeM _) )
    println( "threeM: " + exec(threeM(_,_)) )

    val two: String => Int = (s) => { 2 }
    val three: (String, Int) => Int = (s,i) => { 3 }
    println( "two: " + exec(two) )
    println( "three: " + exec(three) )


One of the things I discovered during these tests was that Java/JVM type erasure seems to make all Function1 (or Function2 or Function3) signatures look the same, and that had an effect on what I wanted to do with overloading function parameter signatures. I hope to write more about that in the future, but for the moment I just wanted to put this code out here so I’ll remember to come back to it one day.

Effects of type erasure

One thing worth noting is that when I compile the above code into .class files and then decompile it, the exec functions look like this:

public static int exec(Function2 function2) {
    return Test$.MODULE$.exec(function2);

public static int exec(Function1 function1) {
    return Test$.MODULE$.exec(function1);

public static int exec(Function0 function0) {
    return Test$.MODULE$.exec(function0);

As shown, JVM type erasure has a significant effect here.