What are exact rules for a function to be considered for Single Abstract Method conversion? In the following code there are two very similar cases, one is compiled, second is not, when compiled with Scala 2.12.4:
trait SAM {
def apply(a: Int, b: Int): Unit
}
def callSAM(sam: SAM): Unit = {
sam(0, 1)
}
def iAmSam(f: (Int, Int) => Unit) = {
def lf(a: Int, b: Int) = f(a, b)
callSAM(f) // does not work - error:
// type mismatch:
// found (Int, Int) => Unit,
// required SAM
callSAM(lf) // works. What is the difference?
callSAM(f(_, _)) // works (lambda)
callSAM((a, b) => f(a, b)) // works (lambda)
}
What is the reason callSAM(lf)
works and callSAM(f)
does not? I have found a mention in Scala 2.12 release notes, which says:
Note that only lambda expressions are converted to SAM type instances, not arbitrary expressions of FunctionN type
The lf
does not look like lambda expression to me. Were the rules relaxed after 2.12.0? When lf
is accepted, why f
is not?
f
is just an object, and falls exactly under
arbitrary expressions of FunctionN type
lf
is the name of a method and when used as expression it's a shorthand for lf _
which in turn expands to (x, y) => lf(x, y)
, which is a lambda expression.