模式繫結
在 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 版中預設啟用。
本文中