Scala 宏:检查 symbol/type 是否为 Tuple

Scala macros: Check if symbol/type is Tuple

在类型化的黑盒宏(隐式物化器)中,如何检查 TypeSymbol 是否为元组?有明显的模式匹配解决方案或类似的解决方案,但是有没有我可以在任何地方找到的 isTuple 方法?

到目前为止我知道我可以做到这一点:

def typed[A : c.WeakTypeTag]: Symbol = weakTypeOf[A].typeSymbol

object TupleSymbols {
  val tuple2 = typed[(_, _)]
  val tuple3 = typed[(_, _, _)]
  // ... and so on
}

有没有比上面的怪物更理智的方法?

  import c.universe._
  import Flag._

  def tuple(i: Int) = {
    def list = (1 to i).toList
    c.typecheck(
      ExistentialTypeTree(
        tq"(..${list map (i => Ident(TypeName(s"_$i")))})", //just like (_,_, ...)
        list map (i =>
          TypeDef(Modifiers(DEFERRED | SYNTHETIC), TypeName(s"_$i"), List(), TypeBoundsTree(EmptyTree, EmptyTree))
          )
      )
    )
  }

//测试

println(tuple(2).tpe <:< typeOf[(_, _)])//true 
println(tuple(3).tpe <:< typeOf[(_, _, _)])//true 

编辑1:

def asTuple(tpe: Type): Boolean = {
  def allTuple = 1 to 22 map { i =>
    val typeNames = 1 to i map (e => TypeName(s"_$e"))
    tq"(..$typeNames) forSome {..${typeNames.map(e => q"type $e")} }"
  } map (t => c.typecheck(t).tpe)

  allTuple.exists(_ <:< tpe)
}

//测试

println(asTuple(typeOf[Int])) // false 
println(asTuple(typeOf[(_, _)])) // true 
println(asTuple(typeOf[(_, _,_)])) // true 

根据评论中的建议,通过简单的匹配就可以很好地解决这个问题。

def isTuple(tpe: Type): Boolean = {
  tpe.typeSymbol.fullName.startsWith("scala.Tuple")
}