【问题标题】:Abstract reflection API in Scala 2.10Scala 2.10 中的抽象反射 API
【发布时间】:2013-06-04 04:25:51
【问题描述】:

Scala 2.10 带有一个很棒的反射 API。但是,它有两个入口点:运行时 Universe 和宏上下文 Universe。

使用运行时反射时,应导入scala.reflect.runtime.universe。在宏实现中使用反射时,您应该从上下文中导入 Universe。

是否可以编写一些适用于两种环境的代码?应该如何获得universe

考虑这个例子:

class MyReflection(val u: scala.reflect.api.Universe) {
  import u._

  def foo[T: TypeTag] = implicitly[TypeTag[T]].tpe.members // returns MyReflection.u.MemberScope
}
val x = new MyReflection(scala.reflect.runtime.universe)
val members: scala.reflect.runtime.universe.MemberScope = x.foo[String] // BANG! Compiler error

由于类型不匹配,这将无法编译。同时,很明显,此示例中的scala.reflect.runtime.universe.MemberScopeMyReflection.u.MemberScope 共享相同的API。有没有办法对不同的宇宙进行抽象?

或者我可能在尝试导出反射工件(本例中为MemberScope)时做一些哲学上的错误?

【问题讨论】:

    标签: scala reflection macros scala-macros


    【解决方案1】:

    你可以只接受宇宙作为参数:

    class MyReflection(val u: scala.reflect.api.Universe) {
      import u._
    
      def foo[T : TypeTag] = implicitly[TypeTag[T]].tpe.members
    }
    
    
    val x = new MyReflection(scala.reflect.runtime.universe)
    

    请注意,您必须通过 MyReflection 的实例引用 Universe 才能正确获取路径相关类型。

    val members: x.u.MemberScope = x.foo[String]
    

    查看this question 了解更多示例和选项。

    【讨论】:

    • 感谢您的回答!虽然这个提示是一个解决方案,但它对我来说有一个明显的缺点。我已经用它的描述更新了这个问题。
    • 欢迎来到路径依赖类型的缺点。你别无选择,只能在MyReflection范围内做你想做的事,或者参考MyReflectionUniverse的实现。查看更新的答案。
    • 谢谢!看起来this(请参阅“编写更大的宏”部分)会对我有所帮助。
    猜你喜欢
    • 2012-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多