2016-11-11 8 views
1

タイプ付きブラックボックスマクロ(暗黙のマテリアライザー)では、TypeまたはSymbolがタプルであるかどうかを確認するにはどうすればよいですか?パターンマッチングなどの明らかな解決策がありますが、どこでも見つけることができるisTupleメソッドがありますか?Scalaマクロ:シンボル/タイプがタプルであるかどうかを確認します

は、これまでのところ、私はこれを行うことができます知っている:

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を使用すると、準座は簡単です。私はあなたが私の質問を理解しているかどうかはわかりません、任意の型が手動ですべてのタプル型を定義せずにタプルであるかどうかを調べたいと思います。 – flavian

関連する問題