Scala 中的 eta 扩展是什么?
What is the eta expansion in Scala?
我是 Scala 新手。刚听说"eta expansion"这个词,大概知道意思就是把一个方法扩展成一个函数对象。但是我在SO中发现很少有系统地介绍它的资源。
我很好奇 eta 扩展在 Scala 中是如何工作的。哪些场景需要eta扩容? eta expansion 在 Scala 中是如何实现的?
我大概知道在这种情况下:
def someMethod(x: Int): Int = x * x
someMethod _
将大致翻译成这样的新函数对象:
new Function1[Int, Int] {
def apply(x: Int): Int = x * x
}
这就是 Scala 所做的一切吗?
http://scala-lang.org/files/archive/spec/2.11/06-expressions.html#method-values 中给出了定义和一些示例。
someMethod _
will roughly be translated to a new function object like this:
不完全是:实际上是
new Function1[Int, Int] {
def apply(x: Int): Int = someMethod(x)
}
差异很重要,例如如果 someMethod
在某处被覆盖。
Is it all that Scala does?
您还需要考虑如果该方法采用多个参数列表(您得到一个 returns 一个函数的函数)或按名称的参数会发生什么。
What are the scenarios that eta expansion are needed?
当您特别要求时(例如someMethod _
)。
当您使用一种方法(带参数)时,需要函数类型(或 Scala 2.12 中的 SAM 类型)的值。例如
def foo(f: Int => Int) = ???
foo(someMethod)
就是这样。
请注意,由于类型推断、隐式等原因,使用 eta 扩展和带占位符的匿名函数 (someMethod(_)
) 可能会有不同的行为。
Eta expansion 在高层次上,是一个将方法转化为函数的过程。为什么?什么?他们不一样吗?让我们解释一下:
Scala 中的一个方法就是我们所知道的def someMethodName(SomePramList): SomeReturnType
。它以 def
开头。它可能有参数列表,甚至可能超过 1 个。例如:
def numAdder(num1: Int)(num2: Int): Int =
num1 + num2
一个函数,或lambda
函数类似于:(SomeParams) => SomeReturnType
。例如:
val aFunction: Int => Int => Int = (num1: Int) => (num2: Int) => num1 + num2
了解函数的重要一点是,此语法基本上是 FunctionN.apply
方法的语法糖。
What are the scenarios that eta expansion are needed?
一些例子:
示例 1 - 在 map
(或 filter
、flatMap
等)
中应用方法
写这样的代码:
def addPlus1(x: Int): Int = x + 1
List(1,2,3).map(addPlus1)
编译器需要在 map
中有一个 函数 。因此,它将给定的方法转换为函数:
List(1,2,3).map(x => addPlus1(x))
。这是 Eta expansion
.
示例 2 - currying
定义柯里化方法时,例如:
def numAdder(num1: Int)(num2: Int): Int =
num1 + num2
他们创建了一个函数,例如:
val curriedFunction: Int => Int = numAdder(4)
//or
val curriedFunction2 = numAdder(4) _
我们从一个方法中定义了一个函数。这是 Eta expansion
.
更多例子
定义了一个接受函数值的方法:
def someMethod(f: () => Int): Int = f()
def method(): Int = 10
然后运行:
someMethod(method)
会将方法 method
转换为函数。这是Eta expansion
我是 Scala 新手。刚听说"eta expansion"这个词,大概知道意思就是把一个方法扩展成一个函数对象。但是我在SO中发现很少有系统地介绍它的资源。
我很好奇 eta 扩展在 Scala 中是如何工作的。哪些场景需要eta扩容? eta expansion 在 Scala 中是如何实现的?
我大概知道在这种情况下:
def someMethod(x: Int): Int = x * x
someMethod _
将大致翻译成这样的新函数对象:
new Function1[Int, Int] {
def apply(x: Int): Int = x * x
}
这就是 Scala 所做的一切吗?
http://scala-lang.org/files/archive/spec/2.11/06-expressions.html#method-values 中给出了定义和一些示例。
someMethod _
will roughly be translated to a new function object like this:
不完全是:实际上是
new Function1[Int, Int] {
def apply(x: Int): Int = someMethod(x)
}
差异很重要,例如如果 someMethod
在某处被覆盖。
Is it all that Scala does?
您还需要考虑如果该方法采用多个参数列表(您得到一个 returns 一个函数的函数)或按名称的参数会发生什么。
What are the scenarios that eta expansion are needed?
当您特别要求时(例如
someMethod _
)。当您使用一种方法(带参数)时,需要函数类型(或 Scala 2.12 中的 SAM 类型)的值。例如
def foo(f: Int => Int) = ??? foo(someMethod)
就是这样。
请注意,由于类型推断、隐式等原因,使用 eta 扩展和带占位符的匿名函数 (someMethod(_)
) 可能会有不同的行为。
Eta expansion 在高层次上,是一个将方法转化为函数的过程。为什么?什么?他们不一样吗?让我们解释一下:
Scala 中的一个方法就是我们所知道的def someMethodName(SomePramList): SomeReturnType
。它以 def
开头。它可能有参数列表,甚至可能超过 1 个。例如:
def numAdder(num1: Int)(num2: Int): Int =
num1 + num2
一个函数,或lambda
函数类似于:(SomeParams) => SomeReturnType
。例如:
val aFunction: Int => Int => Int = (num1: Int) => (num2: Int) => num1 + num2
了解函数的重要一点是,此语法基本上是 FunctionN.apply
方法的语法糖。
What are the scenarios that eta expansion are needed?
一些例子:
示例 1 - 在 map
(或 filter
、flatMap
等)
写这样的代码:
def addPlus1(x: Int): Int = x + 1
List(1,2,3).map(addPlus1)
编译器需要在 map
中有一个 函数 。因此,它将给定的方法转换为函数:
List(1,2,3).map(x => addPlus1(x))
。这是 Eta expansion
.
示例 2 - currying
定义柯里化方法时,例如:
def numAdder(num1: Int)(num2: Int): Int =
num1 + num2
他们创建了一个函数,例如:
val curriedFunction: Int => Int = numAdder(4)
//or
val curriedFunction2 = numAdder(4) _
我们从一个方法中定义了一个函数。这是 Eta expansion
.
更多例子
定义了一个接受函数值的方法:
def someMethod(f: () => Int): Int = f()
def method(): Int = 10
然后运行:
someMethod(method)
会将方法 method
转换为函数。这是Eta expansion