现在你已经了解了如何编写自己的高阶函数,让我们快速了解一个更实际的示例。
想象一下,List
类没有自己的 map
方法,而你想编写自己的方法。创建函数时,第一步是准确地陈述问题。仅关注 List[Int]
,你陈述
我想编写一个
map
方法,该方法可用于将函数应用于给定的List[Int]
中的每个元素,并将转换后的元素作为新列表返回。
根据该陈述,你开始编写方法签名。首先,你知道你希望接受一个函数作为参数,并且该函数应将 Int
转换为某种泛型类型 A
,因此你编写
def map(f: (Int) => A)
使用泛型类型需要在参数列表之前声明类型符号,因此添加该类型符号
def map[A](f: (Int) => A)
接下来,您知道 map
也应接受 List[Int]
def map[A](f: (Int) => A, xs: List[Int])
最后,您还知道 map
返回一个转换后的 List
,其中包含泛型类型 A
的元素
def map[A](f: (Int) => A, xs: List[Int]): List[A] = ???
这将处理方法签名。现在,您需要做的就是编写方法主体。map
方法将给定的函数应用于给定列表中的每个元素,以生成一个新的转换列表。执行此操作的一种方法是使用 for
表达式
for (x <- xs) yield f(x)
for x <- xs yield f(x)
for
表达式通常会使代码变得异常简单,对于我们的目的,这最终将成为整个方法主体。
将其与方法签名放在一起,您现在拥有一个独立的 map
方法,该方法适用于 List[Int]
def map[A](f: (Int) => A, xs: List[Int]): List[A] =
for (x <- xs) yield f(x)
def map[A](f: (Int) => A, xs: List[Int]): List[A] =
for x <- xs yield f(x)
使其泛型化
作为奖励,请注意 for
表达式不会执行任何依赖于 List
中的类型为 Int
的操作。因此,您可以用泛型类型参数 B
替换类型签名中的 Int
def map[A, B](f: (B) => A, xs: List[B]): List[A] =
for (x <- xs) yield f(x)
def map[A, B](f: (B) => A, xs: List[B]): List[A] =
for x <- xs yield f(x)
现在,您拥有一个 map
方法,该方法适用于任何 List
。
这些示例演示了 map
按预期工作
def double(i : Int): Int = i * 2
map(double, List(1, 2, 3)) // List(2, 4, 6)
def strlen(s: String): Int = s.length
map(strlen, List("a", "bb", "ccc")) // List(1, 2, 3)
现在您已经了解如何编写接受函数作为输入参数的方法,让我们来看看返回函数的方法。
此页面的贡献者
内容
- 简介
- Scala 特性
- 为什么选择 Scala 3?
- Scala 入门
- 你好,世界!
- REPL
- 变量和数据类型
- 控制结构
- 领域建模
- 方法
- 一等函数
- 单例对象
- 集合
- 上下文抽象
- 顶级定义
- 总结
- 类型初探
- 字符串插值
- 控制结构
- 领域建模
- 工具
- OOP 建模
- FP 建模
- 方法
- 方法特性
- Scala 3 中的主方法
- 总结
- 函数
- 匿名函数
- 函数变量
- Eta 展开
- 高阶函数
- 编写自己的 map 方法
- 创建返回函数的方法
- 总结
- 打包和导入
- Scala 集合
- 集合类型
- 集合方法
- 总结
- 函数式编程
- 什么是函数式编程?
- 不可变值
- 纯函数
- 函数即值
- 函数式错误处理
- 总结
- 类型和类型系统
- 推断类型
- 泛型
- 交集类型
- 并集类型
- 代数数据类型
- 协变和逆变
- 不透明类型
- 结构化类型
- 依赖函数类型
- 其他类型
- 上下文抽象
- 扩展方法
- 上下文参数
- 上下文边界
- 给定导入
- 类型类
- 多重相等
- 隐式转换
- 总结
- 并发
- Scala 工具
- 使用 sbt 构建和测试 Scala 项目
- 工作表
- 与 Java 交互
- 面向 Java 开发人员的 Scala
- 面向 JavaScript 开发人员的 Scala
- 面向 Python 开发人员的 Scala
- 下一步