2016-11-11 65 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