我目前正在从这本书中学习 Scala 多阶段编程
Scalable Metaprogramming in Scala 3
,取自作者网站https://github.com/nicolasstucki/nicolasstucki/raw/main/Scalable%20Metaprogramming%20in%20Scala%203.pdf
这个问题是关于最后一个片段,即第 151 页给出的与 Reflection API 相关的片段。
class memoize extends MacroAnnotation:
override def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] =
import quotes.reflect._
tree match
case DefDef(name, params@List(TermParamClause(List(param))), tpt, Some(impl)) =>
(Ref(param.symbol).asExpr, impl.asExpr) match
case ('{ $paramRef: arg }, '{ $implExpr: res }) =>
val cacheSymbol = Symbol.newVal(tree.symbol.owner, name + "Cache"
,
TypeRepr.of[Map[arg, res]], Flags.EmptyFlags, Symbol.noSymbol)
val fibCacheRef = Ref(cacheSymbol).asExprOf[Map[arg, res]]
val cacheVal = ValDef(cacheSymbol, Some('{ Map.empty[arg, res] }.asTerm))
val newDef = DefDef.copy(tree)(name, params, tpt, Some(
'{
if !$fibCacheRef.contains($paramRef) then
$fibCacheRef($paramRef) = $implExpr
$fibCacheRef($paramRef)
}.asTerm
))
case _ => List(cacheVal, newDef)
report.errorAndAbort("expected a`def` with a single parameter list")
}
我无法让编译器通过使用定义类型声明的函数参数。 我还尝试使用第一个片段中给出的导入方案https://scala-lang.org/api/3.3_LTS/docs/docs/reference/metaprogramming/reflection.html
导致
import scala.quoted.*
object Main {
@_root_.scala.annotation.experimental
class memoize extends MacroAnnotation {
override def transform(using Quotes)(tree: reflect.Definition): List[reflect.Definition] = {
import quoted.quotes.reflect.*
...
}
}
}
但是编译器抱怨
[error] 10 | override def transform(using Quotes)(tree: reflect.Definition): List[reflect.Definition] = {
[error] | ^^^^^^^^^^^^^^^^^^
[error] | type Definition is not a member of reflect
有什么线索或建议吗?
我目前将矛头指向
scala2.13
复古兼容性,它错过了此功能。还是没找到出路。
祝您度过一个愉快的夜晚,希望这条消息不会在您最忙碌的时刻打扰您。
问候
reflect
模块是quotes: Quotes
值的一部分,通常在方法内部导入:
// named Quotes instance
def macroMethod(arguments)(using quoted: Quotes): Result = {
import quoted.* // reflect et all
}
// anonymous Quotes instance
def macroMethod(arguments)(using Quotes): Result = {
// uses:
// transparent inline def quotes(using q: Quotes): q.type = q
import quotes.* // reflect et all
}
要使其在使用
reflect.Definition
的宏注释的签名中可用,您必须使用命名的 Quoted
实例,然后使用路径相关类型:
import scala.annotation.experimental
@experimental
class memoize extends MacroAnnotation {
override def transform(using q: Quotes)(
tree: q.reflect.Definition // <- q. prefix needed
): List[q.reflect.Definition] = { // <- q. prefix needed
import q.* // from here on, q. prefix is no lonfer needed
...
}
}