起初我曾相信使用下划线来制作闭包(例如println _
)只是使用箭头的简写(例如x => println x
),但我最近才知道你也可以做以下事情:
def f(a: Int, b: Int) = a + 2 * b
List(1, 2, 3).reduce(f _)
鉴于我过去的假设,f _
看起来像一个闭包,它只接受一个参数并将一个参数传递给f
。我假设它会告诉我它无法编译,因为f
需要两个参数,reduce
应该期望一个带有两个参数的函数。但它就像我写的一样:
def f(a: Int, b: Int) = a + 2 * b
List(1, 2, 3).reduce((x, y) => f(x, y))
这里发生了什么?使用下划线创建闭包的规则是什么?
答案 0 :(得分:5)
没什么特别的。方法reduce
采用一个函数,该函数需要两个Int
并生成一个Int
,因此为其提供f
可以正常工作。请注意,当您说f _
实际扩展为x => f x
时(或者,如果有两个参数,例如(x, y) => f(x, y)
)。您也可以只提供f
,然后直接使用它,而无需额外的匿名函数包装器。
通过f _
将方法转换为函数称为eta-expansion(完全披露:我写了那篇文章)。差异很微妙; function是一个值,而一个方法就是你调用它所定义的对象的方法,例如, myObject.myMethod
。功能可以单独使用,也可以保存在集合中。将方法f
直接定义为函数val f: (Int, Int) => Int = (a: Int, b: Int) => a + b
或者使用类型推断val f = (a: Int, b: Int) => a + b
。
顺便说一下,我不知道这是一个封闭。