从 Scala 3 宏的上下文来看:
def aMacroImpl[T](using Type[T], Quotes): Expr[SpecialMap[_, _, _]] = {
import quotes.reflect._
val TRepr: TypeRepr = TypeRepr.of[T]
val TSym: Symbol = TRepr.typeSymbol
val SrtdMapSym: Symbol = TypeRepr.of[scala.collection.SortedMap].typeSymbol
TSym.declaredFields.map{ f => TRepr.memberType(f) }.collect {
case fieldTyepRepr if fieldTyepRepr.derivesFrom(SrtdMapSym) =>
val fieldType = Inferred(fieldTyepRepr).tpe.asType
fieldType match {
////////////////////////////////////////////////////////////
case ... => // <-- This line is the subject of the question.
////////////////////////////////////////////////////////////
'{SpecialMap.apply[k, v, sm](/* omitted for brevity*/)}
}
}
}
// More context.
object SpecialMap {
import scala.collection.mutable.Builder
def apply[K, V, SM <: SortedMap[K, V]](bldr: Builder[(K, V), SM]): SpecialMap[K, V, SM] = {
SpecialMap[K, V, SM](bldr.result)
}
}
case class SpecialMap[K, V, SM <: SortedMap[K, V]](wrapedMap: SM)
什么样的语法可以代替“...在上面的代码片段中,它可以匹配给定的 SortedMap 类型,以便它可以检索所有三个类型参数:k、v 和 sm?
询问者已经尝试过以下方法:
- 不完整的解决方案:
/*a*/ case '[sm] => // provides sm, but not k or v
/*b*/ case '[SortedMap[k, v]] => // provides k and v but not sm
- 直接编译错误:
/*a*/ case '[sm[k, v]] => // sm$given1.Underlying does not take type parameters
/*b*/ case '[_[k, v]] => // ']' expected, but '[' found
/*c*/ case 'sm[k, v] => /* symbol literal 'sm is no longer supported, use a string literal
"sm" or an application Symbol("sm") instead, or enclose in braces '{sm} if you want a
quoted expression. For now, you can also `import language.deprecated.symbolLiterals` to
accept the idiom, but this possibility might no longer be available in the future. */
/*d*/
import language.deprecated.symbolLiterals
fieldType match {
case 'sm[k, v] => // '=>' expected, but '[' found
/*e*/
type SM[k, v] = fieldType match { // Not found: type fieldType
case '[sm] => Type[sm]
case _ => quotes.reflect.report.errorAndAbort("uh oh")
}
/*h*/
case '[sm] =>
type SM[k1, v1] <: SortedMap[k1, v1] = Type[sm] // cannot combine bound and alias
/*f*/
case '[sm] =>
type SM = Type[sm]
fieldType match {
case '[SM[k, v]] => // SM does not take type parameters
- 微妙的编译器错误:
// Examples in this snippet lose the association between k, v, sm, and SortedMap[k,v].
// All yield the following error:
// Type argument sm does not conform to upper bound collection.SortedMap[k, v]
/*a*/
case '[SortedMap[k, v]] =>
fieldType match {
case '[sm] if TypeRepr.of[sm].derivesFrom((TypeRepr.of[SortedMap[k, v]]).typeSymbol) =>
'{SpecialMap.apply[k, v, sm](/***/)} // ... sm does not conform ...
/*b*/
fieldType match {
case '[sm] =>
fieldType match {
case '[SortedMap[k, v]] if TypeRepr.of[sm].derivesFrom((TypeRepr.of[SortedMap[k, v]]).typeSymbol) =>
'{SpecialMap.apply[k, v, sm](/***/)} // ... sm does not conform ...
/*c*/
(fieldType, fieldType) match {
case ('[sm], '[SortedMap[k, v]]) =>
'{SpecialMap.apply[k, v, sm](/***/)} // ... sm does not conform ...
/*d*/
fieldType match {
case '[sm1] =>
type SM[k1,v1] = Type[sm1]
fieldType match {
case '[SM[k, v]] =>
'{SpecialMap.apply[k, v, SM[k, v]](/***/)} // ... SM does not conform ...
/*e*/
fieldType match {
case '[sm1] =>
fieldType match {
case '[SortedMap[k, v]] =>
type SM[k,v] = Type[sm1]
'{SpecialMap.apply[k, v, SM[k, v]](/***/)} // ... SM does not conform ...
当然,显式编写从 SortedMap 派生的每个已知具体类适用于任何特定项目,但库应该容纳 SortedMap 特征的未知继承者。
有没有办法捕获所有三种类型参数及其相互依赖的关系?
谢谢您的考虑。