Scala中的eta扩展是什么?

时间:2016-09-12 07:09:51

标签: scala eta-expansion

我是Scala的新手。我刚刚听到了“eta扩展”一词。并且大致知道它意味着将方法扩展为函数对象。但我发现很少有资源可以系统地介绍它。

我很好奇eta扩展在Scala中是如何工作的。需要进行eta扩展的场景是什么?以及如何在Scala中实现 eta扩展

我粗略地知道在这种情况下:

def someMethod(x: Int): Int = x * x

someMethod _将大致转换为新的函数对象,如下所示:

new Function1[Int, Int] {
  def apply(x: Int): Int = x * x
}

Scala的全部内容吗?

2 个答案:

答案 0 :(得分:14)

定义和一些例子在http://scala-lang.org/files/archive/spec/2.11/06-expressions.html#method-values中给出。

  

someMethod _将大致转换为新的函数对象,如下所示:

不完全:它实际上是

new Function1[Int, Int] {
  def apply(x: Int): Int = someMethod(x)
}

差异很重要,例如如果在某处覆盖someMethod

  

Scala的全部内容吗?

如果方法采用多个参数列表(您获得一个返回函数的函数)或按名称参数,您还需要考虑会发生什么。

  

需要进行eta扩展的场景是什么?

  1. 当您特别要求时(例如someMethod _)。

  2. 当您使用一个方法(带参数)时,需要一个函数类型的值(或Scala 2.12中的SAM类型)。 E.g。

    def foo(f: Int => Int) = ???
    
    foo(someMethod)
    
  3. 那就是它。

  4. 请注意,使用eta-expansion和带占位符的匿名函数(someMethod(_))可能因类型推断,隐含等原因而表现不同。

答案 1 :(得分:7)

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方法的语法糖。

哪些情况下需要扩展eta?

一些例子:

示例1-在map(或filterflatMap等)内部应用方法

编写这样的代码:

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-curring

定义咖喱方法时,例如:

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