Scala 3 導入可選括號語法和新的控制結構語法。代價是對既有語法做一些最小的限制。
其他語法變更旨在讓語法更不令人意外,更一致。
值得注意的是,大多數變更可以在 Scala 3 遷移編譯期間自動處理。
不相容性 | Scala 2.13 | Scala 3 遷移重寫 | Scalafix 規則 |
---|---|---|---|
受限制的關鍵字 | ✅ | ||
程序語法 | 棄用 | ✅ | ✅ |
lambda 參數周圍的括號 | ✅ | ||
傳遞參數的開括號縮排 | ✅ | ||
錯誤的縮排 | |||
_ 作為類型參數 |
|||
+ 和 - 作為類型參數 |
受限制的關鍵字
Scala 3 關鍵字清單可以在 此處 找到。常規 關鍵字不能用作識別符,而 軟 關鍵字不受限制。
對於從 Scala 2.13 遷移到 Scala 3 的問題,只有新的 常規 關鍵字子集存在問題。它由下列組成
enum
export
given
then
=>>
?=>
例如,以下程式碼可以用 Scala 2.13 編譯,但不能用 Scala 3 編譯。
object given { // In Scala 3, Error: given is now a keyword.
val enum = ??? // In Scala 3, Error: enum is now a keyword.
println(enum) // In Scala 3, Error: enum is now a keyword.
}
Scala 3 遷移編譯 將程式碼重寫為
-object given {
+object `given` {
- val enum = ???
+ val `enum` = ???
- println(enum)
+ println(`enum`)
}
程序語法
程序語法已被棄用一段時間,並已從 Scala 3 中刪除。
以下程式碼現在是非法的
object Bar {
def print() { // In Scala 3, Error: Procedure syntax no longer supported; `: Unit =` should be inserted here.
println("bar")
}
}
Scala 3 遷移編譯 將程式碼重寫為。
object Bar {
- def print() {
+ def print(): Unit = {
println("bar")
}
}
lambda 參數周圍的括號
當 lambda 的參數後跟其類型時,現在需要用括號將其括起來。以下程式碼無效。
val f = { x: Int => x * x } // In Scala 3, Error: parentheses are required around the parameter of a lambda.
Scala 3 遷移編譯 將程式碼重寫為
-val f = { x: Int => x * x }
+val f = { (x: Int) => x * x }
傳遞參數的開括號縮排
在 Scala 2 中,可以透過將參數括在花括號中,在換行後傳遞參數。儘管這是一種有效的編碼方式,但 Scala 風格指南 並不鼓勵這種編碼方式,且在 Scala 3 中也不再支援。
test("my test")
{ // In Scala 3, Error: This opening brace will start a new statement.
assert(1 == 1)
}
Scala 3 遷移編譯器 會縮排區塊的第一行。
test("my test")
-{
+ {
assert(1 == 1)
}
此遷移規則也適用於其他模式,例如在換行後限定類型。
type Bar = Foo
-{
+ {
def bar(): Int
}
較好的解決方案是撰寫
-test("my test")
-{
+test("my test") {
assert(1 == 1)
}
錯誤的縮排
Scala 3 編譯器現在需要正確的縮排。以下這段在 Scala 2.13 中編譯的程式碼,由於縮排的關係,現在無法編譯。
def bar: (Int, Int) = {
val foo = 1.0
val bar = foo // [E050] In Scala 3, type Error: value foo does not take parameters.
(1, 1)
} // [E007] In Scala 3, type Mismatch Error: Found Unit, Required (Int, Int).
必須修正縮排。
def bar: (Int, Int) = {
val foo = 1.0
val bar = foo
- (1, 1)
+ (1, 1)
}
可以使用 Scala 格式化工具,例如 scalafmt 或 IntelliJ Scala 格式化工具 來防止這些錯誤。請注意,這些工具可能會變更專案的整個程式碼風格。
_
作為類型參數
在 Scala 2.13 中允許將 _
識別碼用作類型參數,即使它從未在 Scala 2 規格中提及。它用於 fastparse 的 API 中,與內容限制結合使用,以宣告一個隱含參數。
def foo[_: Foo]: Unit = ???
在此,方法 foo
採用類型參數 _
和類型為 Foo[_]
的隱含參數,其中 _
參照類型參數,而不是萬用字元符號。
Martin Odersky 將此模式描述為「巧妙利用 scalac 編譯器錯誤」(來源)。
Scala 3 編譯器不再允許這種模式
-- [E040] Syntax Error: src/main/scala/anonymous-type-param.scala:4:10
4 | def foo[_: Foo]: Unit = ()
| ^
| an identifier expected, but '_' found
解決方案是給予參數一個有效的識別名稱,例如 T
。這不會破壞二進制相容性。
-def foo[_: Foo]: Unit = ???
+def foo[T: Foo]: Unit = ???
+
和 -
作為類型參數
+
和 -
在 Scala 3 中不是類型參數的有效識別碼,因為它們是保留給變異註解的。
您不能再寫 def foo[+]
或 def foo[-]
。
-- Error: src/main/scala/type-param-identifier.scala:2:10
2 | def foo[+]: +
| ^
| no `+/-` variance annotation allowed here
解決方案是選擇另一個有效的識別碼,例如 T
。
然而,+
和 -
仍然是有效的類型識別碼。您可以寫 type +
。