Correspondencia de literales de función con quasiquotes en scala.
macros scala-macros (1)
Con el último plugin de Paradise para 2.10 y en vainilla 2.11 puedes hacerlo de esta manera:
val q"(..$args) => $body" = f.tree
Acabo de probarlo con el proyecto de ejemplo de paraíso con Macros.scala
siguiente:
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"()")
}
}
Y Test.scala
:
object Test extends App {
Macro((x: Int) => x + 1)
}
Puede leer más sobre el manejo de árboles de funciones con cuasicotas en el capítulo correspondiente de la guía de cuasicotas .
Esta pregunta es similar en motivación a mi pregunta anterior (aunque se trata de un problema que encontré en un contexto diferente ).
Puedo hacer coincidir patrones en una función literal con bastante facilidad sin 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
}
}
Que funciona así:
scala> QQExample.funcDemo((a: Int) => a.toString)
List(val a: Int = _)
a.toString()
Ahora supongamos que quiero usar cuasicotas para hacer el mismo tipo de partido de manera más flexible. Lo siguiente también coincidirá con esa función, e imprime lo que esperaríamos.
case q"($x: $t) => $body" => List(x, t, body) foreach println
Pero si quiero especificar el tipo en el patrón, no coincide:
case q"($x: Int) => $body" => List(x, body) foreach println
Y ninguno de los siguientes incluso compilará:
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
¿Es posible especificar el tipo de un parámetro al hacer coincidir en una función literal con cuasiquotes, o hacer coincidir en un número desconocido de parámetros?