Scala 宏:检查 symbol/type 是否为 Tuple
Scala macros: Check if symbol/type is Tuple
在类型化的黑盒宏(隐式物化器)中,如何检查 Type
或 Symbol
是否为元组?有明显的模式匹配解决方案或类似的解决方案,但是有没有我可以在任何地方找到的 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")
}
在类型化的黑盒宏(隐式物化器)中,如何检查 Type
或 Symbol
是否为元组?有明显的模式匹配解决方案或类似的解决方案,但是有没有我可以在任何地方找到的 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")
}