【问题标题】:What is the eta expansion in Scala?Scala 中的 eta 扩展是什么?
【发布时间】:2017-01-19 13:53:20
【问题描述】:

我是 Scala 新手。刚刚听说过“eta扩展”这个词,大致知道就是将一个方法扩展为一个函数对象。但是我在 SO 中发现很少有系统地介绍它的资源。

我很好奇 Scala 中的 eta 扩展是如何工作的。需要eta扩容的场景有哪些?以及 eta 扩展 是如何在 Scala 中实现的?

我大致知道在这种情况下:

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

someMethod _ 大致会被翻译成这样的新函数对象:

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

这就是 Scala 所做的一切吗?

【问题讨论】:

标签: scala eta-expansion


【解决方案1】:

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 类型)的值。例如

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

请注意,使用 eta-expansion 和带有占位符 (someMethod(_)) 的匿名函数可能会因类型推断、隐式等而有所不同。

【讨论】:

    【解决方案2】:

    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 - 柯里化

    定义柯里化方法时,例如:

    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-02
      • 2014-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多