【问题标题】:Lifting string variable using Scala quasiquotes使用 Scala quasiquotes 提升字符串变量
【发布时间】:2017-06-05 16:44:29
【问题描述】:

这是我面临的问题的简化版本,但根本问题仍然存在。 调用宏后,我想动态生成案例类。我能够从宏调用等中检索参数。我遇到的问题是尝试在准引号中使用字符串变量。我基本上想要以下内容:

def expand_impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
    import c.universe._

    val toGen = "case class Foo()"

    val toReturn = c.Expr[Any](
        q"$toGen"
    )
    toReturn
}

但是,不会生成案例类。现在我知道如果我将 toGen 更改为 q"case class Foo()" 它将起作用,但是 toGen 是一个字符串,我将在其他一些返回字符串的处理之后生成,所以我不能这样做。 像这样编译它并手动查看 toReturn 的值,我得到以下信息:

Expr[Any]("case class Foo()")

字符串 toGen 只是简单地粘贴在引号中,这意味着没有生成案例类。

我已经寻找过类似的问题,但在任何地方都找不到这个示例。如何在准引号内取消引用字符串变量的双引号?

【问题讨论】:

  • 如果你想使用准引号,你必须对每个嵌套表达式使用它们,否则你只会提升字符串表达式。为什么构造case类声明时不能使用准引号?
  • 这个想法是这样的:val toGen = someMethod()someMethod() 返回的字符串类似于“case class Foo()”。如果正确理解您,您是在建议我在返回案例类时使用准引号?然而这是我的问题所在,因为someMethod() 不会总是返回相同的案例类,它会根据输入等动态生成它们并返回一个字符串。
  • 问题是准引号不解析字符串,所以每当你要提升的表达式表示为字符串时,你就不能使用它们。在这种情况下,您必须解析字符串,就像 Régis Jean-Gilles 在他的回答中演示的那样。

标签: scala macros scala-quasiquotes


【解决方案1】:

Context 上定义了一个parse 方法。它返回一个Tree,并且因为可以在准引号中插入树,所以您可以很容易地将解析与准引号混合和匹配。 举例:

scala> :paste
// Entering paste mode (ctrl-D to finish)

import scala.reflect.macros.whitebox.Context
import scala.language.experimental.macros

def test_impl(c: Context)(): c.Tree = {
  import c.universe._
  val tree = c.parse("""println(2)""")
  q"println(1); $tree; println(3)"
}
def test(): Unit = macro test_impl

// Exiting paste mode, now interpreting.

import scala.reflect.macros.whitebox.Context
import scala.language.experimental.macros
test_impl: (c: scala.reflect.macros.whitebox.Context)()c.Tree
defined term macro test: ()Unit

scala> test()
1
2
3

在此示例中,我定义了一个 def 宏,但它应该与宏注释一样工作(如您的情况)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-26
    • 2020-08-20
    相关资源
    最近更新 更多