Frage

I have a next code:

object TestMacro {

  def test[A](vval: List[A]) = macro testImpl[A]

  def testImpltestImpl[A: c.WeakTypeTag](c: Context)(vval: c.Expr[List[A]]) = {
    import c.universe._

    println(vval) // =>  Expr[Nothing](immutable.this.List.apply[Int](1, 2, 3))

    reify{} 
  }
}

Example:

test(List(1,2,3))

How to get real type List[Int] from Expr and get List instance with (1,2,3) values in macro?

War es hilfreich?

Lösung

You could use method showRaw to get Tree structure like this:

import reflect.runtime.universe._
showRaw{ reify{ List(1, 2, 3) } }
// Expr(Apply(Select(Ident(scala.collection.immutable.List), newTermName("apply")), List(Literal(Constant(1)), Literal(Constant(2)), Literal(Constant(3)))))

reify returns Expr.

Result with indentations:

Expr(
  Apply(
    Select(
      Ident(scala.collection.immutable.List),
      newTermName("apply")
    ),
    List(
      Literal(Constant(1)),
      Literal(Constant(2)),
      Literal(Constant(3))
    )
  )
)

So you could deconstruct this tree:

val vval = reify{ List(1, 2, 3) }
val l =
  vval.tree match {
    case Apply(_, l) => l
  }
// List[reflect.runtime.universe.Tree] = List(1, 2, 3)


val ints =
  l map {
    case Literal(Constant(i: Int)) => i
  }
// List[Int] = List(1, 2, 3)

Note that it will work only in case when your method test is called like test(List(1, 2, 3)). It will fail on val l = List(1, 2, 3); test(l). It will fail even on test(List(1+1)).

The only useful application for such parameters extraction is macros-based string interpolation like this.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top