Scala 3 — 书籍

编写自己的 map 方法

语言

现在你已经了解了如何编写自己的高阶函数,让我们快速了解一个更实际的示例。

想象一下,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)

现在您已经了解如何编写接受函数作为输入参数的方法,让我们来看看返回函数的方法。

此页面的贡献者