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)

現在你有一個可與任何 List 搭配使用的 map 方法。

這些範例說明了 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)

現在你已經看過如何撰寫將函式作為輸入參數的方法,讓我們來看一下會傳回函式的方法。

此頁面的貢獻者