2016-11-11 36 views
1

在输入的黑盒宏(隐式实现器)中,如何检查TypeSymbol是否为元组?有明显的模式匹配或类似的解决方案,但有没有一种isTuple方法,我可以在任何地方找到?Scala宏:检查符号/类型是否为Tuple

到目前为止,我知道我能做到这一点:

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

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

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

+0

检查该名称是否与'scala.Tuple \ d *'匹配? –

+0

@AlexeyRomanov这是最好的吗?感觉脆弱但可行。 – flavian

+0

我当然会喜欢它定义'tuple2'等,但我不知道是否有更好的选择。 –

回答

0

根据评论中的建议,这可以用简单的匹配很好地处理。

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

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 

EDIT1:

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 
+0

谢谢,但我不想构建元组类型,或使用AST,quasiquotes更容易。我不确定你是否理解我的问题,我正在检查是否一个任意类型是一个元组而不需要手动定义所有的元组类型。 – flavian