Nic*_*oli 6 generics scala tuples scala-macros scala-3
我在 Scala 3 中定义了以下特征:
\ntrait A[T <: Tuple]\nRun Code Online (Sandbox Code Playgroud)\n然后,我使用 Scala 3 宏创建具有此特征的对象,对元组的实际类型执行进一步检查T;特别是,我想检查元组的所有类型(T_1,\xe2\x80\xa6,T_n)T是否是另一个给定类型的子类型B:
trait B\nprivate def allSubtypesOfB[T <: Tuple: Type](using quotes: Quotes): Boolean = {\n import quotes.reflect.*\n case '[Nothing] => false // I don't want nothing to be in T\n case '[head *: tail] if TypeRepr.of[head] <:< TypeRepr.of[B] => allSubtypesOfB[tail]\n case '[EmptyTuple] => true\n case _ => false\n}\n\ninline def createA[T <: Tuple] = ${ createAImpl[T] }\nprivate def createAImpl[T <: Tuple: Type](using quotes: Quotes): Expr[A[T]] = {\n import quotes.reflect.*\n if !allSubtypesOfB[T] then report.error("All types in T must be subtypes of B")\n // ... create instance of A\n}\nRun Code Online (Sandbox Code Playgroud)\n问题是,稍后我需要为元组 type 中的每种类型调用T具有以下签名的方法:
def doSomethingWithBSubtype[T <: B] = ??? // Do something with type T\nRun Code Online (Sandbox Code Playgroud)\n所以,代码看起来像这样:
\nprivate def createAImpl[T <: Tuple: Type](using quotes: Quotes): Expr[A[T]] = {\n import quotes.reflect.*\n if !allSubtypesOfB[T] then report.error("All types in T must be subtypes of B")\n Type.of[T] match {\n case '[head *: tail] => doSomethingWithBSubtype[head]\n case '[EmptyTuple] => ???\n }\n // ... create instance of A\n}\nRun Code Online (Sandbox Code Playgroud)\n此代码不会编译,因为编译器表示它必须是要在方法中使用的head子类型。然而,通过前面的例子,我已经确保里面的所有类型都是 的子类型。有没有办法强制编译器识别为 的子类型?BdoSomethingWithBSubtypeifmatchTBheadB
宏有编译时和运行时之分。主要代码有编译时和运行时(使用宏)。宏的运行时间就是主代码的编译时间。
createAImpl该行内部if !allSubtypesOfB[T]...确保 的所有类型在 的运行时T都是 的子类型。但是当你调用时,你需要知道它是编译时的子类型,所以你还没有来自运行时的信息()。BcreateAImpldoSomethingWithBSubtype[head]headBcreateAImplcreateAImplif !allSubtypesOfB[T]...
你可以做
case '[head *: tail] => doSomethingWithBSubtype[head & B]
Run Code Online (Sandbox Code Playgroud)
也许像下面这样的事情是可能的
Type.of[T] match {
case '[head *: tail] =>
'{foo[head]} match {
case '{
type h <: B
foo[`h`]
} => doSomethingWithBSubtype[h]
}
case '[EmptyTuple] => ???
}
// outside def createAImpl, otherwise "access to method foo from wrong staging level"
def foo[A] = ???
Run Code Online (Sandbox Code Playgroud)
https://docs.scala-lang.org/scala3/guides/macros/quotes.html#type-variables-in-quoted-patterns
在某些情况下,我们需要定义一个被多次引用或具有某种类型界限的模式变量。为了实现这一点,可以使用
type t类型模式变量在模式开始处创建模式变量。
什么 Scala 3 语法可以匹配宏上下文中的类型及其类型参数?