3

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

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

结果是

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

因为$在 quasiquotes 内需要一个tree.

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

有效,但是非常难看,并且我收到 Intellij 警告,该警告c.literal已弃用,我应该改用 quasiquotes。

所以......我该怎么做?

更新

回应弗拉维安的评论:

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
  }
}

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

2 回答 2

7

你需要一个TermName编译器原语。

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

这是解决它的一种方法:

import c.universe._

val world = TermName("Earth")
val tree = q"""println("Hello" + ${world.decodedName.toString})"""
于 2016-10-26T11:14:30.437 回答
0

我刚开始学习宏福。

对于那些也在探索 Scala 2 Macros / Scalameta Quasiquotes 的人,在我看来,最简单的方法如下(使用 SBT 1.5.5;内联解释):

scala> import scala.language.experimental.macros
     | import scala.reflect.macros.blackbox
     |
     | object UnquoteString {
     |
     |   def helloWorld(): Unit = macro Impl.helloWorld
     |
     |   object Impl {
     |     def helloWorld(c: blackbox.Context)(): c.Expr[Unit] = {
     |       import c.universe._
     |
     |       val world = "Earth" // or any other value here...
     |
     |       val msg = s"Hello $world" // build the entire string with it here...
     |
     |       implicitly[Liftable[String]] // as we can lift 'whole' string values with this Liftable[_]...
     |
     |       val tree = q"""println($msg)""" // quasi-unquote the entire string here...
     |
     |       c.Expr[Unit](Block(Nil, tree))
     |     }
     |   }
     | }
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
object UnquoteString

scala> UnquoteString.helloWorld()
Hello Earth

scala>

以下更改也将起作用

      val tree = q"""println("Hello, " + $world)""" // quasi-unquote the string to append here...
于 2021-10-16T07:59:29.903 回答