Scala 3宏中如何递归实现类型参数的规范化命名?
解决Scala 3元编程中递归规范化类型名称的问题
要实现递归规范化嵌套类型的名称,你需要把类型处理逻辑抽成可递归调用的辅助函数,对每个类型参数递归执行规范化操作。以下是修改后的代码:
object Playpen: import scala.quoted.* inline def recursiveCanonicalName[T]: String = ${Playpen.recursiveCanonicalNameImpl[T]} def recursiveCanonicalNameImpl[T](using Quotes)(using Type[T]): Expr[String] = canonicalizeTypeRepr(TypeRepr.of[T]) // 递归处理TypeRepr的辅助函数 private def canonicalizeTypeRepr(repr: TypeRepr)(using Quotes): Expr[String] = import quotes.reflect.* repr.widenTermRefByName.dealias match case AppliedType(name, args) => // 处理类型名称 val nameExpr = Expr(name.dealias.simplified.show) // 递归处理每个类型参数,得到对应的表达式 val argExprs = args.map(canonicalizeTypeRepr) // 拼接参数表达式,用逗号分隔 val joinedArgs = argExprs.reduceOption { (a, b) => Expr.splice(a) + Expr(",") + Expr.splice(b) }.getOrElse(Expr("")) // 拼接最终的类型字符串表达式 nameExpr + Expr("[") + joinedArgs + Expr("]") case _ => // 基础类型直接返回规范化后的名称 Expr(repr.dealias.simplified.show)
关键修改说明:
- 提取辅助函数:将类型处理逻辑移到
canonicalizeTypeRepr,方便对任意TypeRepr(包括类型参数)递归调用。 - 递归处理参数:遇到
AppliedType时,对每个类型参数递归调用canonicalizeTypeRepr,确保嵌套类型(比如Seq[String]里的String)也被规范化。 - Expr拼接:使用
Expr.splice将递归生成的字符串表达式正确拼接,避免直接字符串拼接导致的递归失效问题。
测试验证:
修改后再测试嵌套类型:
@ macroplay.Playpen.recursiveCanonicalName[Map[Seq[String],Seq[String]]] res: String = "scala.collection.immutable.Map[scala.collection.immutable.Seq[java.lang.String],scala.collection.immutable.Seq[java.lang.String]]"
可以看到,Seq的参数String也被正确规范化为java.lang.String,实现了多层嵌套类型的递归处理。
内容的提问来源于stack exchange,提问作者Steve Waldman
相关产品推荐
相关产品推荐

