Scala 3 — 书籍

Eta 扩展

语言

当你查看 Scala 集合类上的 map 方法的 Scaladoc 时,你会看到它被定义为接受一个函数

def map[B](f: (A) => B): List[B]
           -----------

事实上,Scaladoc 明确指出,“f 是应用于每个元素的函数。”但尽管如此,你仍然可以将一个方法传递到 map 中,并且它仍然有效

def times10(i: Int) = i * 10   // a method
List(1, 2, 3).map(times10)     // List(10,20,30)

你是否曾想过它是如何工作的——你如何将一个方法传递到 map 中,而它却期望一个函数

这项技术被称为Eta 扩展。它将方法类型的表达式转换为函数类型的等效表达式,并且它会无缝且安静地执行此操作。

方法和函数之间的差异

从历史上看,方法一直是类定义的一部分,尽管在 Scala 3 中,你现在可以在类外部使用诸如 顶级定义扩展方法 之类的方法。

与方法不同,函数本身就是完整的对象,使它们成为一流实体。

它们的语法也不同。此示例展示了如何定义一个方法和一个执行相同任务的函数,即确定给定的整数是否为偶数

def isEvenMethod(i: Int) = i % 2 == 0         // a method
val isEvenFunction = (i: Int) => i % 2 == 0   // a function

函数确实是一个对象,因此你可以像使用任何其他变量一样使用它,例如将其放入列表中

val functions = List(isEvenFunction)
// this example shows the Scala 2 error message
val methods = List(isEvenMethod)
                   ^
error: missing argument list for method isEvenMethod
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `isEvenMethod _` or `isEvenMethod(_)` instead of `isEvenMethod`.

相反,从技术上讲,方法不是一个对象,因此在 Scala 2 中,你不能将方法放入 List 中,至少不能直接放入,如下例所示

val functions = List(isEvenFunction)   // works
val methods = List(isEvenMethod)       // works

对于 Scala 3,重要的部分是 Eta 扩展技术得到了改进,因此现在当你尝试将方法用作变量时,它就可以正常工作了——你不必自己处理手动转换。

对于这本入门书籍来说,需要了解的重要事项是

  • Eta 扩展是 Scala 技术,它允许你像使用函数一样使用方法
  • 该技术在 Scala 3 中得到了改进,几乎完全无缝

有关此工作原理的更多详细信息,请参阅参考文档中的 Eta 扩展页面

此页面的贡献者