当你查看 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 扩展页面。
此页面的贡献者
内容
- 简介
- Scala 特性
- 为什么选择 Scala 3?
- Scala 尝鲜
- Hello, World!
- REPL
- 变量和数据类型
- 控制结构
- 领域建模
- 方法
- 一流函数
- 单例对象
- 集合
- 上下文抽象
- 顶级定义
- 总结
- 首次了解类型
- 字符串插值
- 控制结构
- 领域建模
- 工具
- OOP 建模
- FP 建模
- 方法
- 方法特性
- Scala 3 中的主方法
- 总结
- 函数
- 匿名函数
- 函数变量
- Eta 扩展
- 高阶函数
- 编写自己的 map 方法
- 创建返回函数的方法
- 总结
- 打包和导入
- Scala 集合
- 集合类型
- 集合方法
- 总结
- 函数式编程
- 什么是函数式编程?
- 不可变值
- 纯函数
- 函数即值
- 函数式错误处理
- 总结
- 类型和类型系统
- 推断类型
- 泛型
- 交集类型
- 联合类型
- 代数数据类型
- 变体
- 不透明类型
- 结构化类型
- 依赖函数类型
- 其他类型
- 上下文抽象
- 扩展方法
- 上下文参数
- 上下文边界
- 给定导入
- 类型类
- 多重相等性
- 隐式转换
- 总结
- 并发
- Scala 工具
- 使用 sbt 构建和测试 Scala 项目
- 工作表
- 与 Java 交互
- 面向 Java 开发人员的 Scala
- 面向 JavaScript 开发人员的 Scala
- 面向 Python 开发人员的 Scala
- 下一步去哪里