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
// DOESN’T WORK
//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(_,_)) )
// CREATING ACTUAL “VAL FUNCTIONS” WORKS EASILY
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.