scala - 将值插入quasiquote

Use*_*291 2 macros scala string-interpolation scala-quasiquotes

不幸的是,最直观的方式,

val world = "Earth"
val tree = q"""println("Hello $world")"""
Run Code Online (Sandbox Code Playgroud)

结果是

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

因为$在quasiquotes中期望a tree.

val world = "Earth"
val tree = q"""println(${c.literal(s"Hello $world")})"""
Run Code Online (Sandbox Code Playgroud)

工作,但非常难看我得到一个Intellij警告,c.literal不赞成,我应该使用quasiquotes,而不是.

那么......我该怎么做?

UPDATE

回应flavian的评论:

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
  }
}
Run Code Online (Sandbox Code Playgroud)

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

fla*_*ian 7

你需要一个TermName或者什么是编译器原语.

真正的问题是你在没有意识到混合插值器.hello world中的插值器实际上是一个字符串插值器,而不是像你建议的那样擅长取消引用树的quasiquote.

这是一种方法:

import c.universe._

val world = TermName("Earth")
val tree = q"""println("Hello" + ${world.decodedName.toString})"""
Run Code Online (Sandbox Code Playgroud)