带有函数的奇怪 SAM 规则
Strange SAM rules with functions
要考虑进行单一抽象方法转换的函数的确切规则是什么?在下面的代码中有两种非常相似的情况,一种是编译的,第二种是没有的,当用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)
}
callSAM(lf)
有效而 callSAM(f)
无效的原因是什么?我在 Scala 2.12 release notes 中发现了一个提及:
Note that only lambda expressions are converted to SAM type instances, not arbitrary expressions of FunctionN type
lf
在我看来不像是 lambda 表达式。 2.12.0之后规则放宽了吗?当 lf
被接受时,为什么 f
不被接受?
f
只是一个对象,恰好属于
arbitrary expressions of FunctionN type
lf
是方法的名称,当用作表达式时,它是 lf _
的 shorthand,后者又扩展为 (x, y) => lf(x, y)
,这是一个 lambda 表达式.
要考虑进行单一抽象方法转换的函数的确切规则是什么?在下面的代码中有两种非常相似的情况,一种是编译的,第二种是没有的,当用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)
}
callSAM(lf)
有效而 callSAM(f)
无效的原因是什么?我在 Scala 2.12 release notes 中发现了一个提及:
Note that only lambda expressions are converted to SAM type instances, not arbitrary expressions of FunctionN type
lf
在我看来不像是 lambda 表达式。 2.12.0之后规则放宽了吗?当 lf
被接受时,为什么 f
不被接受?
f
只是一个对象,恰好属于
arbitrary expressions of FunctionN type
lf
是方法的名称,当用作表达式时,它是 lf _
的 shorthand,后者又扩展为 (x, y) => lf(x, y)
,这是一个 lambda 表达式.