在 GitHub 上編輯此頁面

模式繫結

在 Scala 2 中,val 定義和 for 表達式的樣式繫結是鬆散型別的。在編譯時,仍會接受潛在失敗的比對,但可能會影響程式的執行時期行為。從 Scala 3.2 開始,型別檢查規則將會收緊,以便在編譯時報告警告。

樣式定義中的繫結

val xs: List[Any] = List(1, 2, 3)
val (x: String) :: _ = xs   // error: pattern's type String is more specialized
                            // than the right-hand side expression's type Any

此程式碼在 Scala 3.2(以及在 -source future 設定下的較早 Scala 3.x)中會產生編譯時警告,而它會在 Scala 2 中以 ClassCastException 在執行時期失敗。在 Scala 3.2 中,僅當樣式為不可推翻時,才允許樣式繫結,也就是說,如果右手邊的型別符合樣式的型別。例如,下列範例是正確的

val pair = (1, true)
val (x, y) = pair

有時,即使樣式可推翻,也想要分解資料。例如,如果在某個時間點知道清單 elems 非空,則可能想要像這樣分解它

val first :: rest = elems   // error

這在 Scala 2 中有效。事實上,這是 Scala 2 規則的典型使用案例。但在 Scala 3.2 中,它會產生警告。可以透過標記右手邊為 @unchecked 註解來避免警告

val first :: rest = elems: @unchecked   // OK

這會讓編譯器接受樣式繫結。如果 elems 永遠不會為空的基礎假設錯誤,它可能會在執行時期產生錯誤。

for 表達式中的模式繫結

類似的變更套用於 for 表達式中的模式。例如

val elems: List[Any] = List((1, 2), "hello", (3, 4))
for (x, y) <- elems yield (y, x) // error: pattern's type (Any, Any) is more specialized
                                 // than the right-hand side expression's type Any

此程式碼在 Scala 3.2 中會產生編譯時期警告,而在 Scala 2 中,清單 elems 會經過篩選,僅保留與模式 (x, y) 相符的元組類型元素。可以在 Scala 3 中透過在模式前加上 case 來取得篩選功能

for case (x, y) <- elems yield (y, x)  // returns List((2, 1), (4, 3))

語法變更

for 表達式中的產生器可以加上 case 前綴。

Generator      ::=  [‘case’] Pattern1 ‘<-’ Expr

移轉

Scala 3.0 支援新的語法。然而,為了讓 Scala 2 和 Scala 3 之間的交叉編譯順利進行,變更的行為和額外的類型檢查僅在 -source future 設定下啟用。這些功能將在語言的 3.2 版中預設啟用。