鉴于
scala> def method(x: Int) = x
method: (x: Int)Int
scala> val func = (x: Int) => x
func: Int => Int = <function1>
请考虑以下代码:
scala> method _
res0: Int => Int = <function1>
scala> func(_)
res1: Int => Int = <function1>
scala> func _
res2: () => Int => Int = <function0>
我可以理解res0
是eta扩展而res1
等同于lambda函数(x) => func(x)
。但我无法弄清楚res2
的输出。有人可以帮我解释一下吗?
答案 0 :(得分:6)
这实际上有点棘手。首先,让我们看看REPL之外会发生什么:
当func
是一个局部变量时没有工作:
object Main extends App {
def foo() = {
val f = (_: Int) + 1
f _
}
println(foo())
}
[error] /tmp/rendereraEZGWf9f1Q/src/main/scala/test.scala:8: _ must follow method; cannot follow Int => Int
[error] f _
[error] ^
但如果你把它放在def foo
之外,它会编译:
object Main extends App {
val f = (_: Int) + 1
val f1 = f _
println(f1)
}
因为f
既是Main
的字段,又是没有参数的方法,它返回此字段的值。
最后一块是REPL将每一行包装成一个对象(因为Scala不允许代码出现在特征/类/对象之外),所以
scala> val func = (x: Int) => x
func: Int => Int = <function1>
真的像
object Line1 {
val func = (x: Int) => x
}
import Line1._
// print result
所以下一行的func
引用Line1.func
这是一种方法,因此可以进行eta扩展。
答案 1 :(得分:3)
您已经使用eta Expansion将res2
转换为一个接受0参数的函数,并返回一个带有单个参数的函数。
res2: () => Int => Int = <function0>
所以你现在可以这样做:
val zero = func _
val f: Int => Int = zero()
答案 2 :(得分:2)
val func1 = func _
这将返回一个不带参数的函数0并返回func
函数。
你可以使用它:
func1()(2) // outputs 2
您可以无限制地继续进行此类扩展:
val func2 = func1 _
func2()()(2) // outputs 2
答案 3 :(得分:2)
要回答有关res2
的问题,我们会使用附加的下划线_
语法来部分应用函数。
所以
scala> func _
表示您已部分应用了<function1>
。
这会产生一个新的curry形式,其第一个函数采用零参数(因此<function0>
)
() =>
返回原始<function1>
,其中包含1个参数。
Int => Int = <function1>
完整的结果是功能链。
res2: () => Int => Int = <function0>
可能对您有用的规则是函数与右侧相关联,因此以下内容是等效的。
() => Int => Int
() => (Int => Int)
This other post可能对您有用。