2013-09-01 10 views
25

To pytanie jest podobne w motywacji do mojego previous question (chociaż chodzi o problem, który napotkałem w different context).Dopasowywanie literałów funkcyjnych z quasiquotes w Scala

mogę wzór spotkanie na funkcję dosłownym dość łatwo bez quasiquotes:

import scala.reflect.macros.Context 
import scala.language.experimental.macros 

object QQExample { 
    def funcDemo(f: Int => String) = macro funcDemo_impl 
    def funcDemo_impl(c: Context)(f: c.Expr[Int => String]) = { 
    import c.universe._ 

    f.tree match { 
     case Function(ps, body) => List(ps, body) foreach println 
     case _ => c.abort(
     c.enclosingPosition, 
     "Must provide a function literal." 
    ) 
    } 

    c.literalUnit 
    } 
} 

Który działa tak:

scala> QQExample.funcDemo((a: Int) => a.toString) 
List(val a: Int = _) 
a.toString() 

Załóżmy teraz chcę użyć quasiquotes zrobić tego samego rodzaju meczu bardziej elastycznie. Następujące elementy będą również pasować do tej funkcji i wydrukują to, czego oczekujemy.

case q"($x: $t) => $body" => List(x, t, body) foreach println 

Ale jeśli chcę, aby określić typ w strukturze, to nie pasuje:

case q"($x: Int) => $body" => List(x, body) foreach println 

I żaden z poniższych nawet skompilować:

case q"$p => $body"  => List(p, body) foreach println 
case q"($p) => $body" => List(p, body) foreach println 
case q"..$ps => $body" => List(ps, body) foreach println 
case q"(..$ps) => $body" => List(ps, body) foreach println 

Czy to możliwe, określić typ parametru podczas dopasowywania literału funkcyjnego do quasiquotes lub do dopasowania na nieznanej liczbie parametrów?

+9

To błąd. Wszystkie wzorce w twoim ostatnim bloku kodu powinny działać dla anonimowych funkcji pojedynczego argumentu. Postępuj zgodnie z [SI-7803] (https://issues.scala-lang.org/browse/SI-7803), aby otrzymać powiadomienie, gdy poprawka zostanie scalona z wzorcem. –

+0

@DenShabalin: Dzięki! –

+5

Poprawka znajduje się w kolejce żądań pobierania 2.11. Po jego scaleniu zsynchronizuję ją z wersją 2.10. Byłem też trochę w błędzie, mówiąc, że wszystkie wzory będą działać. Będziesz musiał użyć nawiasów na argumentach (to jest wzorach 2 i 4). –

Odpowiedz

4

Z najnowszą wtyczkę raj dla 2.10 i 2.11 w wanilii można zrobić to w ten sposób:

val q"(..$args) => $body" = f.tree 

Właśnie przetestowane go z paradise example project z następujących Macros.scala:

import language.experimental.macros 
import scala.reflect.macros.Context 

object Macro { 
    def apply(f: Any): Any = macro impl 
    def impl(c: Context)(f: c.Expr[Any]) = { import c.universe._ 
    val q"(..$args) => $body" = f.tree 
    println(s"args = $args, body = $body") 
    c.Expr(q"()") 
    } 
} 

I Test.scala :

object Test extends App { 
    Macro((x: Int) => x + 1) 
} 

Możesz przeczytać w więcej o obsłudze drzew funkcji z quasiquotes w corresponding chapter of quasiquote guide.

Powiązane problemy