2013-07-01 7 views
5

Ich habe ein WeakTypeTag irgendeiner Art in meinem Makro, und ich möchte, um Code zu generieren, wie folgt:Ist es möglich, Apply von WeakTypeTag innerhalb eines Scala-Makros zu generieren?

macroCreate[SomeObject] // => SomeObject(1) 

Die Definition eines Makros in etwa so sein wird:

def macroCreate[A] = macro _macroCreate[A] 
def _macroCreate[A](c: Context)(implicit wtt: c.WeakTypeTag[A]) = { 
    c.Expr(Apply(Select(???, newTermName("apply")), List(c.literal(1).tree))) 
} 

Das Problem ist, , wie bekomme ich Select für den gegebenen Typ?

Ich kann eine Problemumgehung des Konvertierens des Typs in Zeichenfolge, Aufteilen "." und dann Erstellen eines Select aus der Liste der Zeichenfolgen verwenden, aber das scheint hacky.

Ist es möglich, ein Select direkt vom Typ Tag zu erstellen?

Antwort

8

Sie können das Symbol des Begleitobjekt bekommen und dann die Ident(sym: Symbol): Ident Factory-Methode des Universums verwenden:

def macroCreate[A] = macro _macroCreate[A] 

def _macroCreate[A](c: Context)(implicit wtt: c.WeakTypeTag[A]) = { 
    import c.universe._ 

    c.Expr(
    Apply(
     Select(Ident(wtt.tpe.typeSymbol.companionSymbol), newTermName("apply")), 
     c.literal(1).tree :: Nil 
    ) 
) 
} 

Und dann:

scala> case class SomeObject(i: Int) 
defined class SomeObject 

scala> macroCreate[SomeObject] 
res0: SomeObject = SomeObject(1) 

scala> macroCreate[List[Int]] 
res1: List[Int] = List(1) 

Wenn Sie wirklich bedeuten, dass SomeObject die Art der ist Objekt (dh nicht der Typ, der seinen Begleiter Klasse), entfernen Sie einfach die .companionSymbol oben.

+2

Ich habe eine kleine bearbeiten ('newTermName' in Select), weil scalac deprecation Warnung auf sie wirft. Vielen Dank! – Rogach

+0

Oh, richtig danke! Zu schnell tippen ... –