2016-07-19 13 views
0

Mit Scala quasiquotes können Sie Bäume wählt einfach bauen, etwa so:Variable Länge „wählen Sie“ s mit quasiquotes

> tq"a.b.MyObj" 
res: Select(Select(Ident(TermName("a")), TermName("b")), TermName("MyObj")) 

Meine Frage ist, wie kann ich dies tun, wenn die Liste der Dinge zur Auswahl (a, b, ... usw.) ist variable Länge (und daher in einer Variablen, die eingefügt werden muss)?

Ich hatte gehofft, funktionieren würde, heben (zB tq"""..${List("a","b","MyObj")}""" aber es funktioniert nicht. Oder vielleicht sogar diese tq"""${List("a","b","MyObj").mkString(".")}""", aber kein Glück.

Gibt es eine Möglichkeit, dies mit quasiquotes zu unterstützen? Oder muss ich nur bauen Der Baum von wählt manuell in diesem Fall?

Antwort

1

Ich glaube nicht, es gibt eine Möglichkeit, dies direkt mit Quasiquotes.Ich bin mir sicher, dass alles wie tq"""${List("a","b","MyObj").mkString(".")}""" wird nicht funktionieren.Mein Verständnis von Quasiquotes ist, dass sie sind nur Zucker für Extraktoren und gelten.

Allerdings bui Wir können einen benutzerdefinierten Extraktor definieren, um das zu tun, was Sie wollen. (By the way, ich bin sicher, dass es ein schöner Weg, dies auszudrücken, aber Sie erhalten die Idee ...)

object SelectTermList { 
    def apply(arg0: String, args: List[String]): universe.Tree = 
    args.foldLeft(Ident(TermName(arg0)).asInstanceOf[universe.Tree]) 
       ((s,arg) => Select(s, TermName(arg))) 

    def unapply(t: universe.Tree): Option[(String,List[String])] = t match { 
    case Ident(TermName(arg0)) => Some((arg0, List())) 
    case Select(SelectTermList(arg0,args),TermName(arg)) => 
     Some((arg0, args ++ List(arg))) 
    case _ => None 
    } 
} 

Dann Sie dies sowohl Konstrukt verwenden können und extrahieren Ausdrücke der Form a.b.MyObj .

Extractor Tests:

scala> val SelectTermList(obj0,selectors0) = q"a.b.c.d.e.f.g.h" 
obj0: String = a 
selectors0: List[String] = List(b, c, d, e, f, g, h) 

scala> val q"someObject.method(${SelectTermList(obj1,selectors1)})" = q"someObject.method(a.b.MyObj)" 
obj1: String = a 
selectors1: List[String] = List(b, MyObj) 

Tests Entsprechendes gilt:

scala> SelectTermList(obj0,selectors0) 
res: universe.Tree = a.b.c.d.e.f.g.h 

scala> q"someObject.method(${SelectTermList(obj1,selectors1)})" 
res: universe.Tree = someObject.method(a.b.MyObj) 

Wie Sie sehen können, kein Problem gibt es die Extraktoren tief in quasi Anführungszeichen mit Verschachtelung, sowohl bei der Konstruktion und zu extrahieren.

Verwandte Themen