scala - 将值插入 quasiquote

标签 scala macros string-interpolation scala-quasiquotes

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

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 已弃用,我应该使用准引号。

那么……我该怎么做呢?

更新

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

给予

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

最佳答案

您需要一个 TermName 或编译器原语。

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

这是一种解决方法:

import c.universe._

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

关于scala - 将值插入 quasiquote,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40260167/

相关文章:

regex - 解析 scala 中的 case 语句

c++ - 下面的宏可能会给应用带来什么问题?

c#:插入字符串以打印输出变量名称和值

javascript - 使用 JavaScript 填写表单

Python:使用自定义分隔符格式化字符串

带有元组切片的 Python 字符串插值?

scala - 使用简单的 SQL 将记录插入事务中的 3 个表时出现异常

java - Apache Spark : Importing jars

postgresql - 如何在 Slick 中调用存储过程并获取返回值(使用 Scala)

macros - 方案:如何在不带括号的语法规则中扩展具有多个变量的模式