3

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

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

4

1 回答 1

5

没有什么特别的事情发生。Methodreduce采用一个需要两个Ints 并产生一个 s的函数Int,因此为它提供一个f可以正常工作。请注意,当您说f _实际扩展为x => f x(或者,如果有两个参数,例如此处,(x, y) => f(x, y))。您也可以只提供f哪些将直接使用,而无需额外的匿名函数包装器。

通过 do 将方法转换为函数f _称为eta-expansion(完全公开:我写了那篇文章)。差异是微妙的;function 是一个值,而 method 是一个方法,您可以在为其定义的对象上调用该方法,例如myObject.myMethod. 函数可以独立存在,可以保存在集合中等。将您的方法f直接定义为函数将是val f: (Int, Int) => Int = (a: Int, b: Int) => a + b,或者,使用类型推断,val f = (a: Int, b: Int) => a + b.

顺便说一句,我不明白这是如何关闭的。

于 2016-10-18T21:30:28.853 回答