在Scala中,使用下划线制作闭包的规则是什么?

时间:2016-10-18 21:08:39

标签: scala scala-placeholder-syntax eta-expansion

起初我曾相信使用下划线来制作闭包(例如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))

这里发生了什么?使用下划线创建闭包的规则是什么?

1 个答案:

答案 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

顺便说一下,我不知道这是一个封闭。