gpt4 book ai didi

scala - 如何在 reify 子句中使用 Scala 宏中计算的类型?

转载 作者:行者123 更新时间:2023-12-03 03:50:43 26 4
gpt4 key购买 nike

我一直在使用 Scala 宏,并在宏中包含以下代码:

    val fieldMemberType = fieldMember.typeSignatureIn(objectType) match {
case NullaryMethodType(tpe) => tpe
case _ => doesntCompile(s"$propertyName isn't a field, it must be another thing")
}

reify{
new TypeBuilder() {
type fieldType = fieldMemberType.type
}
}

如您所见,我已成功获取 c.universe.Type fieldMemberType。这表示对象中某个字段的类型。一旦我明白了,我想在 reify 中创建一个新的 TypeBuilder 对象。 TypeBuilder 是一个带有抽象参数的抽象类。这个抽象参数是fieldType。我希望这个 fieldType 是我之前找到的类型。

运行此处显示的代码会返回fieldMemberType not found。有什么方法可以让 fieldMemberType 在 reify 子句中工作吗?

最佳答案

问题在于,您传递给 reify 的代码本质上将逐字放置在宏展开的位置,而 fieldMemberType 不会在那里表达任何意思。

在某些情况下,您可以使用 splice 将宏扩展时的表达式隐藏到您正在具体化的代码中。例如,如果我们尝试创建此特征的实例:

trait Foo { def i: Int }

并且在宏扩展时有这个变量:

val myInt = 10

我们可以编写以下内容:

reify { new Foo { def i = c.literal(myInt).splice } }

这在这里不起作用,这意味着您将不得不忘记漂亮的小reify并手动写出AST。不幸的是,你会发现这种情况经常发生。我的标准方法是启动一个新的 REPL 并输入如下内容:

import scala.reflect.runtime.universe._

trait TypeBuilder { type fieldType }

showRaw(reify(new TypeBuilder { type fieldType = String }))

这将输出几行 AST,然后您可以将其剪切并粘贴到宏定义中作为起点。然后你摆弄它,替换如下内容:

Ident(TypeBuilder)

这样:

Ident(newTypeName("TypeBuilder"))

以及 FINALFlag.FINAL,依此类推。我希望 AST 类型的 toString 方法与构建它们所需的代码更准确地对应,但您很快就会知道需要更改什么。你最终会得到这样的结果:

c.Expr(
Block(
ClassDef(
Modifiers(Flag.FINAL),
anon,
Nil,
Template(
Ident(newTypeName("TypeBuilder")) :: Nil,
emptyValDef,
List(
constructor(c),
TypeDef(
Modifiers(),
newTypeName("fieldType"),
Nil,
TypeTree(fieldMemberType)
)
)
)
),
Apply(Select(New(Ident(anon)), nme.CONSTRUCTOR), Nil)
)
)

其中 anon 是您预先为匿名类创建的类型名称,constructor 是我用来使这种事情变得更简单的一种便捷方法不那么丑陋(你可以在 this complete working example 的末尾找到它的定义)。

现在,如果我们将这个表达式包装在 this 之类的内容中,我们可以这样写:

scala> TypeMemberExample.builderWithType[String]
res0: TypeBuilder{type fieldType = String} = $1$$1@fb3f1f3

所以它有效。我们采用了 c.universe.Type (我从 builderWithType 上类型参数的 WeakTypeTag 中获取的,但它会起作用与任何旧的 Type 完全相同),并用它来定义 TypeBuilder 特征的类型成员。

关于scala - 如何在 reify 子句中使用 Scala 宏中计算的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13795490/

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