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 中您不能將方法放入 清單 中,至少不能直接放入,如範例所示

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

Scala 3 的重點在於 Eta Expansion 技術的改進,因此現在當您嘗試將方法用作變數時,它就能運作了,您不必自己處理手動轉換。

對於這本入門書籍,您需要知道的重要事項是

  • Eta Expansion 是讓您可以像使用函式一樣使用方法的 Scala 技術
  • Scala 3 中的技術已獲得改進,幾乎完全無縫

有關此運作方式的更多詳細資訊,請參閱參考文件中的 Eta Expansion 頁面

此頁面的貢獻者