gpt4 book ai didi

scala - 如何对先前定义的对象使用 quasiquotes

转载 作者:行者123 更新时间:2023-12-04 09:38:04 24 4
gpt4 key购买 nike

我刚刚开始学习 Scala 编译时反射,并且通过 Scala 官方指南向我介绍了 quasiquotes。

我仍在努力解决的一个概念是,如果我想为已定义的对象生成 AST,我应该如何使用 quasiquotes(或 reify,就此而言)。假设我有一个对象:

object MyObject {
def method1() = "m1"
}

为了得到一棵树,我知道我可以做到

q"""{object MyObject {
def method1() = "m1"
}}
"""

但是,这样做会阻止我在我的作用域中实际定义对象(我还需要将它完全定义在 String 中,从而将所有代码安全抛出窗口之外)。

我想要做的就是得到那棵树是这样的:

object MyObject {
def method1() = "m1"
}

q"$MyObject" // or q"{MyObject}", I still don't fully understand the table on the Scala guide

我想定义对象,然后使用该定义对其执行一些检查(并在编译时抛出一些异常,如果需要的话),使用宏。据我所知,要使用宏,我需要树(或至少是表达式)。

我已经知道如何在运行时使用 Scala 反射进行我想要的检查,但我认为使用 AST 可能是一个好主意(并且,在这个过程中,我会学到一些东西)。不过,我感觉我误解了一些关于如何使用 AST 的基本概念 - 似乎只能根据调用站点上声明的代码生成 AST。我糊涂了。

我在这里误解了什么?

最佳答案

准报价

q"""{object MyObject {
def method1() = "m1"
}}
"""

或者
reify{
object MyObject {
def method1() = "m1"
}
}.tree

只是写树的方法
Block(
List(
ModuleDef(Modifiers(), TermName("MyObject"),
Template(
List(Select(Ident(scala), TypeName("AnyRef"))),
noSelfType,
List(
DefDef(Modifiers(), termNames.CONSTRUCTOR, List(), List(List()), TypeTree(),
Block(List(pendingSuperCall), Literal(Constant(())))
),
DefDef(Modifiers(), TermName("method1"), List(), List(List()), TypeTree(),
Literal(Constant("m1"))
)
)
)
)
),
Literal(Constant(()))
)

使用 context.parse 可以获得相同的结果(编译时)/ toolBox.parse (运行时)来自普通 String
val str: String = 
"""object MyObject {
| def method1() = "m1"
|}""".stripMargin

toolBox.parse(str)

有宏的编译时间和宏的运行时间。有主代码及其运行时的编译时间。宏的运行时间是主代码的编译时间。
MyObject
object MyObject {
def method1() = "m1"
}

MyObject
q"""{object MyObject {
def method1() = "m1"
}}
"""

存在于不同的语境中。前者存在于当前上下文中,后者存在于宏调用点的上下文中。

您可以将树插入(拼接)到树中。您不能将实际对象插入树中。如果您有实际的对象(编译后的树),那么将其插入树中为时已晚。

当您看到某些东西被插入到树中时,这意味着“某些东西”只是编写树的一种紧凑方式,即类型类 Liftable 的实例。
object MyObject {
def method1() = "m1"
}

implicit val myObjectLiftable: Liftable[MyObject.type] = new Liftable[MyObject.type] {
override def apply(value: MyObject.type): Tree =
q"""
object MyObject {
def method1() = "m1"
}"""
}

q"""
class SomeClass {
$MyObject
}"""

我猜你的宏看起来像
def foo[A](a: A) = macro impl[A]

或者
def foo[A] = macro impl[A]

所以你可以这样称呼它 foo(MyObject)foo[MyObject.type]和里面
def impl[A: c.WeakTypeTag](c: blackbox.Context)...

您可以访问 weakTypeOf[A] ,然后是它的符号。拥有符号,您可以拥有方法等的签名。

关于scala - 如何对先前定义的对象使用 quasiquotes,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62458950/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com