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 迁移编译 将代码重写为
过程语法
过程语法已弃用一段时间,并且在 Scala 3 中已删除。
以下代码段现在是非法的
object Bar {
def print() { // In Scala 3, Error: Procedure syntax no longer supported; `: Unit =` should be inserted here.
println("bar")
}
}
Scala 3 迁移编译 将代码重写为。
Lambda 参数周围的括号
当后面跟着其类型时,现在需要将 lambda 的参数括在括号中。以下代码段无效。
val f = { x: Int => x * x } // In Scala 3, Error: parentheses are required around the parameter of a lambda.
Scala 3 迁移编译 将代码重写为
传递参数时的花括号缩进
在 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 迁移编译器 缩进块的第一行。
此迁移规则也适用于其他模式,例如在换行后优化类型。
一个更好的解决方案是编写
错误的缩进
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).
必须修复缩进。
可以通过使用 Scala 格式化工具(例如 scalafmt 或 IntelliJ Scala 格式化工具)来防止这些错误。请注意,这些工具可能会更改项目的整个代码样式。
_
作为类型参数
在 Scala 2.13 中允许将 _
标识符用作类型参数,即使它从未在 Scala 2 规范中提及。它与上下文绑定结合使用,在 fastparse 的 API 中用于声明隐式参数。
def foo[_: Foo]: Unit = ???
此处,方法 foo
采用类型参数 _
和类型为 Foo[_]
的隐式参数,其中 _
指的是类型参数,而不是通配符符号。
Martin Odersky 将此模式描述为“scalac 编译器错误的巧妙利用”(来源)。
Scala 3 编译器不再允许此模式
解决方案是为参数提供一个有效的标识符名称,例如 T
。这不会破坏二进制兼容性。
+
和 -
作为类型参数
+
和 -
在 Scala 3 中不是类型参数的有效标识符,因为它们是为方差注释保留的。
您不能再编写 def foo[+]
或 def foo[-]
。
解决方案是选择另一个有效的标识符,例如 T
。
但是,+
和 -
仍然是通用的有效类型标识符。您可以编写 type +
。