scala - Is it possible to define a macro with variadic parameters, and get a type for each parameter? -
the following obvious variadic function:
def fun(xs: any*) = ???
we can define macro in similar way:
def funimpl(c: context)(xs: c.expr[any]*) = ??? fun(1,"1",1.0)
but in case, arguments typed any
. in fact, compiler knows types @ compile-time, hides us. possible list of arguments and types in macro?
sure—for example:
import scala.language.experimental.macros import scala.reflect.macros.context object demo { def at(xs: any*)(i: int) = macro at_impl def at_impl(c: context)(xs: c.expr[any]*)(i: c.expr[int]) = { import c.universe._ // first let's show can recover types: println(xs.map(_.actualtype)) i.tree match { case literal(constant(index: int)) => xs.lift(index).getorelse( c.abort(c.enclosingposition, "invalid index!") ) case _ => c.abort(c.enclosingposition, "need literal index!") } } }
and then:
scala> demo.at(1, 'b, "c", 'd')(1) list(int(1), symbol, string("c"), char('d')) res0: symbol = 'b scala> demo.at(1, 'b, "c", 'd')(2) list(int(1), symbol, string("c"), char('d')) res1: string = c
note inferred types precise , correct.
note won't work if argument sequence _*
type ascription, of course, , you'll need write following if want catch case , provide useful error message:
def at_impl(c: context)(xs: c.expr[any]*)(i: c.expr[int]) = { import c.universe._ xs.tolist.map(_.tree) match { case typed(_, ident(tpnme.wildcard_star)) :: nil => c.abort(c.enclosingposition, "needs real varargs!") case _ => i.tree match { case literal(constant(index: int)) => xs.lift(index).getorelse( c.abort(c.enclosingposition, "invalid index!") ) case _ => c.abort(c.enclosingposition, "need literal index!") } } }
Comments
Post a Comment