Scala 3 - 反射 API - 类型定义不是 Reflect 的成员

问题描述 投票:0回答:1

我目前正在从这本书中学习 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
复古兼容性,它错过了此功能。还是没找到出路。

祝您度过一个愉快的夜晚,希望这条消息不会在您最忙碌的时刻打扰您。

问候

scala reflection metaprogramming multistage
1个回答
0
投票

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
    ...
  } 
} 
© www.soinside.com 2019 - 2024. All rights reserved.