类型中的通配符参数
类型中通配符参数的语法正在从 _
更改为 ?
。示例
List[?]
Map[? <: AnyRef, ? >: Null]
动机
我们希望使用下划线语法 _
来表示匿名类型参数,使其与值参数列表中的含义保持一致。因此,就像 f(_)
是 lambda x => f(x)
的简写一样,将来 C[_]
将是类型 lambda [X] =>> C[X]
的简写。这将使高阶类型更容易使用。它还将消除这样一个缺陷:用作类型参数时,F[_]
表示 F
是类型构造器,而用作类型时,F[_]
表示它是一个通配符(即存在)类型。将来,无论在何处使用,F[_]
都将表示相同的事物。
我们选择 ?
作为通配符类型的替换语法,因为它与 Java 语法 保持一致。
迁移策略
迁移到新方案很复杂,特别是由于 kind projector 编译器插件仍使用反向约定,其中 ?
表示通配符而不是占位符。幸运的是,kind projector 已将 *
添加为 ?
的替代语法。
通过以下措施,可以逐步迁移
- 在早期版本的 Scala 3 中,
_
和?
都是通配符的合法名称。 - 在 Scala 3.4 中,
_
将被弃用,取而代之的是?
作为通配符的名称。提供了一个-rewrite
选项,用于将一个重写为另一个。 - 在未来的某个时候,
_
的含义将从通配符更改为类型参数的占位符。 - 在
-source future
设置下,一些弃用警告已经可用。
为了平滑使用 kind-projector 的代码库的过渡,我们在命令行选项 -Ykind-projector
下采取以下措施
- 在 Scala 3.0 中,
*
可用作类型参数占位符。 - 在 Scala 3.2 中,
*
已被弃用,取而代之的是_
。提供了一个-rewrite
选项,用于将一个重写为另一个。 - 在 Scala 3.3 中,
*
再次被移除,所有类型参数占位符都将用_
表示。
这些规则使得在使用 kind projector 插件的 Scala 2 和使用编译器选项 -Ykind-projector
的 Scala 3.0 - 3.2 之间进行交叉构建成为可能。
对于希望一次性过渡到将 _
作为类型参数占位符的语法的用户,还有一种迁移路径。使用选项 -Ykind-projector:underscores
,Scala 3 将 _
视为类型参数占位符,将 ?
作为通配符的唯一语法。
要使用旧的 Scala 2 源代码进行交叉编译,同时使用 _
作为占位符,你必须将选项 -Xsource:3 -P:kind-projector:underscore-placeholders
与最新版本的 kind-projector(0.13
及更高版本)和最新版本的 Scala 2(2.13.5
及更高版本和 2.12.14
及更高版本)一起使用