准引号

类型详细信息

语言
此文档页面专门针对 Scala 2 中发布的功能,这些功能已在 Scala 3 中删除或被替代功能所取代。除非另有说明,此页面中的所有代码示例均假定您使用的是 Scala 2。

Denys Shabalin 实验性

空类型

空类型 (tq"") 是表示给定位置的类型不是由用户提供的,而应由编译器推断的规范方法

  1. 方法,其返回类型未知
  2. Val 或 Var,其类型未知
  3. 匿名函数,其参数类型未知

类型标识符

类似于 术语标识符,可以基于名称构造类型标识符

scala> val name = TypeName("Foo")
name: universe.TypeName = Foo

scala> val foo = tq"$name"
foo: universe.Ident = Foo

并通过 解除提升将其反向分解

scala> val tq"${name: TypeName}" = tq"Foo"
name: universe.TypeName = Foo

当使用类型标识符时,建议始终将名称指定为 TypeName。未指定的模式等效于模式变量绑定。

单例类型

单例类型是一种表示正在引用的术语定义类型的途径

scala> val singleton = tq"foo.bar.type".sr
singleton: String = SingletonTypeTree(Select(Ident(TermName("foo")), TermName("bar")))

scala> val tq"$ref.type" = tq"foo.bar.type"
ref: universe.Tree = foo.bar

类型投影

类型投影是选择类型作为其他类型成员的一种基本方式

scala> val proj = tq"Foo#Bar"
proj: universe.SelectFromTypeTree = Foo#Bar

scala> val tq"$foo#$bar" = proj
foo: universe.Tree = Foo
bar: universe.TypeName = Bar

类似于标识符,建议始终将名称指定为 TypeName。未来,非指定匹配行为可能会发生变化。

为了方便,还可以选择术语的类型成员

scala> val int = tq"scala.Int"
int: universe.Select = scala.Int

scala> val tq"scala.$name" = int
name: universe.TypeName = Int

但在语义上,此类选择只是单例类型和类型投影组合的快捷方式

scala> val projected = tq"scala.type#Int"
projected: universe.SelectFromTypeTree = scala.type#Int

最后,类似于表达式,可以通过 superthis 选择成员

scala> val superbar = tq"super.Bar"
superbar: universe.Select = super.Bar

scala> val tq"$pre.super[$parent].$field" = superbar
pre: universe.TypeName =
parent: universe.TypeName =
field: universe.Name = Bar

scala> val thisfoo = tq"this.Foo"
thisfoo: universe.Select = this.Foo

scala> val tq"this.${tpname: TypeName}" = thisfoo
tpname: universe.TypeName = Foo

应用类型

参数化类型的实例化可以通过应用类型(类型应用程序的类型级等效项)来表示

scala> val applied = tq"Foo[A, B]"
applied: universe.Tree = Foo[A, B]

scala> val tq"Foo[..$targs]" = applied
targs: List[universe.Tree] = List(A, B)

非应用类型的解构将导致 targs 被提取为一个空列表

scala> val tq"Foo[..$targs]" = tq"Foo"
targs: List[universe.Tree] = List()

带注释的类型

类似于表达式,类型可以带注释

scala> val annotated = tq"T @Fooable"
annotated: universe.Annotated = T @Fooable

scala> val tq"$tpt @$annot" = annotated
tpt: universe.Tree = T
annot: universe.Tree = Fooable

复合类型

复合类型允许用户使用可选的精炼成员列表来表示多个类型的组合

scala> val compound = tq"A with B with C"
compound: universe.CompoundTypeTree = A with B with C

scala> val tq"..$parents { ..$defns }" = compound
parents: List[universe.Tree] = List(A, B, C)
defns: List[universe.Tree] = List()

即使没有精炼,并且我们只想提取与 with 关键字组合的类型序列,也需要在父类型后添加大括号来表示此类型是复合类型。

另一方面是没有任何显式父类型(又称结构类型)的纯精炼。

scala> val structural = tq"{ val x: Int; val y: Int }"
structural: universe.CompoundTypeTree =
scala.AnyRef {
  val x: Int;
  val y: Int
}

scala> val tq"{ ..$defns }" = structural
defns: List[universe.Tree] = List(val x: Int, val y: Int)

在这里,我们可以看到 AnyRef 是一个父类型,如果我们不提供任何父类型,它将被隐式插入。

存在类型

存在类型由一个类型树和一个定义列表组成

scala> val tq"$tpt forSome { ..$defns }" = tq"List[T] forSome { type T }"
tpt: universe.Tree = List[T]
defns: List[universe.MemberDef] = List(type T)

或者,还有一个下划线表示法

scala> val tq"$tpt forSome { ..$defns }" = tq"List[_]"
tpt: universe.Tree = List[_$1]
defns: List[universe.MemberDef] = List(<synthetic> type _$1)

元组类型

类似于表达式,元组类型只是 TupleN 类的语法糖

scala> val tup2 = tq"(A, B)"
tup2: universe.Tree = scala.Tuple2[A, B]

scala> val tq"(..$tpts)" = tup2
tpts: List[universe.Tree] = List(A, B)

类似地,Unit 类型被认为是一个空元组

scala> val tq"(..$tpts)" = tq"_root_.scala.Unit"
tpts: List[universe.Tree] = List()

值得一提的是,对 Unit 引用进行模式匹配仅限于完全限定路径或包含符号的引用。(请参阅卫生

函数类型

类似于元组,函数类型是 FunctionN 类的语法糖

scala> val funtype = tq"(A, B) => C"
funtype: universe.Tree = _root_.scala.Function2[A, B, C]

scala> val tq"..$foo => $bar" = funtype
foo: List[universe.Tree] = List(A, B)
bar: universe.Tree = C

此页面的贡献者