Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I have a hard time understanding what you're trying to achieve, and why you are using Trees everywhere. Trees are really low level, hard to use, tricky, and it is very difficult to understand what the code does. Quasiquotes (<a href="http://docs.scala-lang.org/overviews/macros/quasiquotes.html" rel="nofollow">http://docs.scala-lang.org/overviews/macros/quasiquotes.html</a>) are the way to go indeed and you can use them on scala 2.10.x production release thanks to the macro paradise plugin (<a href="http://docs.scala-lang.org/overviews/macros/paradise.html" rel="nofollow">http://docs.scala-lang.org/overviews/macros/paradise.html</a>). The you can simply write <code>q"(a: Int) =&gt; {val z = "toShort"; a.z}"</code> and you directly get the tree expression you just typed.</p> <p>To answer your question, the first point is to remember that macros are evaluated at compile time. They therefore can not generate code which depends on a runtime value. This is why the compiler is complaining about your <code>splice</code>. But if you pass a value which can be computed at compile time, typically a literal, then you can use eval to get its value within your macro code. Eval does suffer a bug though, as indicated in scaladoc. It should only be called on untyped trees. So the way to call eval on an <code>s: c.Expr[String]</code> expression would be <code>val s2 = c.eval(c.Expr[String](c.resetAllAttrs(c.tree.duplicate)))</code> which gives you a <code>String</code> you can then use normally in your code, for instance <code>q"(a: Int) =&gt; a.${newTermName(s2)}"</code>.</p> <p>To put it all together, let's imagine you to create a macro that'll output a string value from an object and one of its <code>String</code> field. It'll give something like</p> <pre><code>def attr[A](a: A, field: String): String = macro attrImpl[A] def attrImpl[A: c.WeakTypeTag](c: Context)(a: c.Expr[A], field: c.Expr[String]) = { import c.universe._ val s = c.eval(c.Expr[String](c.resetAllAttrs(field.tree.duplicate))) c.Expr[String](q"a.${newTermName(s)}") } </code></pre> <p>REPL session test:</p> <pre><code>scala&gt; object a { val field1 = "field1"; val field2 = "field2" } defined module a scala&gt; attr(a, "field1") res0: String = field1 scala&gt; attr(a, "field2") res1: String = field2 </code></pre> <p>To understand the difference between compile time and runtime, you can meditate about the following result in REPL ;-)</p> <pre><code>scala&gt; val s = "field1"; attr(a, s) error: exception during macro expansion: scala.tools.reflect.ToolBoxError: reflective compilation has failed: $iw is not an enclosing class at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal.throwIfErrors(ToolBoxFactory.scala:311) at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal.compile(ToolBoxFactory.scala:244) at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl.compile(ToolBoxFactory.scala:408) at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl.eval(ToolBoxFactory.scala:411) at scala.reflect.macros.runtime.Evals$class.eval(Evals.scala:16) at scala.reflect.macros.runtime.Context.eval(Context.scala:6) at .attrImpl(&lt;console&gt;:14) scala&gt; val s = "field1" s: String = field1 scala&gt; attr(a, s) res3: String = field1 </code></pre> <p>Hope it helps ;))</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload