User1291 User1291 - 1 month ago 6
Scala Question

scala - insert value into quasiquote

Unfortunately, the most intuitive way,

val world = "Earth"
val tree = q"""println("Hello $world")"""


results in

Error:(16, 36) Don't know how to unquote here
val tree = q"""println("Hello $world")"""
^


because
$
within quasiquotes expects a
tree
.

val world = "Earth"
val tree = q"""println(${c.literal(s"Hello $world")})"""


works, but is very ugly AND I get an Intellij warning that the
c.literal
is deprecated and I should use quasiquotes, instead.

So ... how do I do this?

UPDATE

In response to flavian's comment:

import scala.language.experimental.macros
import scala.reflect.macros._

object TestMacros {

def doTest() = macro impl

def impl(c: blackbox.Context)(): c.Expr[Unit] = {
import c.universe._ //access to AST classes
/*
val world = "Earth"
val tree = q"""println(${c.literal(s"Hello $world")})"""
*/

val world = TermName("Earth")
val tree = q"""println("Hello $world")"""

tree match {
case q"""println("Hello Earth")""" => println("succeeded")
case _ => c.abort(c.enclosingPosition, s"huh? was: $tree")
}

c.Expr(tree) //wrap tree and tag with its type
}
}


gives

Error:(18, 40) Don't know how to unquote here
val tree = q"""println("Hello $world")"""
^

Answer

You need a TermName or something that's a compiler primitive.

The real problem is that you are mixing interpolators, without realising. The interpolator in hello world is really a string interpolator, not a quasiquote one which is good at unquoting trees as you suggest.

This is one way to go about it:

import c.universe._

val world = TermName("Earth")
val tree = q"""println("Hello" + ${world.decodedName.toString})"""