在 Scala 中,使用下划线进行闭包的规则是什么?
In Scala, what are the rules for making closures with underscores?
一开始我以为用下划线做闭包(例如println _
)只是shorthand用箭头(例如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))
这是怎么回事?使用下划线创建闭包的规则是什么?
没什么特别的。方法 reduce
采用一个函数,该函数需要两个 Int
并生成一个 Int
,因此为它提供一个 f
可以正常工作。请注意,当您说 f _
时,实际上会扩展为 x => f x
(或者,如果有两个参数,例如此处,(x, y) => f(x, y)
)。您也可以只提供 f
,然后将直接使用它,而无需额外的匿名函数包装器。
通过执行 f _
将方法转换为函数称为 eta-expansion(完全披露:我写了那篇文章)。差异是微妙的;函数是一个值,而方法是您在为其定义的对象上调用的方法,例如myObject.myMethod
。函数可以独立存在,也可以保存在集合中等。将方法 f
直接定义为函数将是 val f: (Int, Int) => Int = (a: Int, b: Int) => a + b
或通过类型推断 val f = (a: Int, b: Int) => a + b
.
顺便说一句,我不明白这是一个闭包。
一开始我以为用下划线做闭包(例如println _
)只是shorthand用箭头(例如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))
这是怎么回事?使用下划线创建闭包的规则是什么?
没什么特别的。方法 reduce
采用一个函数,该函数需要两个 Int
并生成一个 Int
,因此为它提供一个 f
可以正常工作。请注意,当您说 f _
时,实际上会扩展为 x => f x
(或者,如果有两个参数,例如此处,(x, y) => f(x, y)
)。您也可以只提供 f
,然后将直接使用它,而无需额外的匿名函数包装器。
通过执行 f _
将方法转换为函数称为 eta-expansion(完全披露:我写了那篇文章)。差异是微妙的;函数是一个值,而方法是您在为其定义的对象上调用的方法,例如myObject.myMethod
。函数可以独立存在,也可以保存在集合中等。将方法 f
直接定义为函数将是 val f: (Int, Int) => Int = (a: Int, b: Int) => a + b
或通过类型推断 val f = (a: Int, b: Int) => a + b
.
顺便说一句,我不明白这是一个闭包。