在 GitHub 上編輯此頁面

過載解析的變更

Scala 3 中的重載解析在三個方面優於 Scala 2。首先,它會考量所有引數清單,而不仅仅是第一個引數清單。其次,它可以推論函式值的參數類型,即使它們在第一個引數清單中。第三,預設引數不再與優先順序相關。

檢視第一個引數清單之外

在選擇一組重載替代方案時,重載解析現在可以考量引數清單。例如,下列程式碼會編譯在 Scala 3 中,而在 Scala 2 中會產生模稜兩可的重載錯誤

def f(x: Int)(y: String): Int = 0
def f(x: Int)(y: Int): Int = 0

f(3)("")     // ok

下列程式碼也會編譯

def g(x: Int)(y: Int)(z: Int): Int = 0
def g(x: Int)(y: Int)(z: String): Int = 0

g(2)(3)(4)     // ok
g(2)(3)("")    // ok

為了讓此功能運作,SLS §6.26.3 中的重載解析規則會增強如下

在函式套用至多個引數清單的情況下,如果在考量 n >= 1 參數清單時,重載解析產生多個競爭的替代方案,則會使用 n + 1 個引數清單重新嘗試解析。

此變更的動機是新的語言功能 擴充方法,其中出現了基於額外引數區塊進行重載解析的需求。

函數值的參數類型

改進了對缺少參數類型的函數值的處理。我們現在可以在重載應用程式的第一個引數清單中傳遞此類值,前提是其餘參數足以選擇重載函數的變體。例如,以下程式碼在 Scala 3 中編譯,而在 Scala2 中會導致缺少參數類型錯誤

def f(x: Int, f2: Int => Int) = f2(x)
def f(x: String, f2: String => String) = f2(x)
f("a", _.toUpperCase)
f(2, _ * 2)

為使此功能正常運作,SLS §6.26.3 中的重載解析規則已修改如下

替換句子

否則,讓 S1,...,Sm 成為透過使用未定義預期類型鍵入每個引數而取得的類型向量。

為以下段落

否則,讓 S1,...,Sm 成為所有引數類型的已知類型向量,其中引數 E已知類型的判定方式如下

  • 如果 E 是缺少一些參數類型的函數值 (p_1, ..., p_n) => B,則 E 的已知類型為 (S_1, ..., S_n) => ?,其中每個 S_i 為參數 p_i 的類型(如果已提供),否則為 ?。在此,? 代表與所有其他類型相容的萬用字元類型
  • 否則,E 的已知類型為使用未定義預期類型鍵入 E 的結果。

樣式比對封閉

{ case P1 => B1 ... case P_n => B_n }

被視為已擴充至函數值

x => x match { case P1 => B1 ... case P_n => B_n }

因此也近似為 ? => ? 類型。

預設引數不再與優先順序相關

在 Scala 2 中,如果在幾個應用程式替代方案中有一個替代方案具有預設引數,則該替代方案會從考量中刪除。這會產生一個不幸的副作用,即為方法的參數新增預設值可能會使此方法在重載呼叫中不可見。

Scala 3 放棄了此區別。具有預設參數的方法不會被視為優先級低於其他方法。