我了解Scala中宏的基本概念,但目前无法执行此操作(简单?):

  • 查找编译器当前可见的所有隐式def s/val,以将其从给定类型转换为另一种类型。

  • 我期望得到的是List对象的Method或类似的东西。我已经使用过enclosingImplicits了,但是总是得到一个空列表,并且不知道下一步该怎么看。

    我需要做些什么才能获得要查找的 list ?

    最佳答案

    在上下文中,从A类型到B类型只能有一个隐式(否则您会得到模棱两可的隐式),因此,如果要查找它:

    import reflect.macros.Context, scala.language.experimental.macros
    
    def fImpl(c: Context): c.Expr[Unit] = {
      import c.mirror._
      println(c.inferImplicitValue(typeOf[Int]))
      c.universe.reify( () )
    }
    def f = macro fImpl
    
    scala> f
    <empty>
    
    scala> implicit val a = 5
    a: Int = 5
    
    scala> f
    $line24.$read.$iw.$iw.$iw.$iw.a
    
    scala> implicit val b = 5
    b: Int = 5
    
    scala> f //result will be empty, but error printed to the log
    error: ambiguous implicit values:
     both value a of type => Int
     and value b of type => Int
     match expected type Int
    <empty>
    

    查找隐式方法:
    def fImpl(c: Context): c.Expr[Unit] = {
          import c.mirror._
          println(c.inferImplicitValue(typeOf[String => Int]))
          c.universe.reify( () )
     }
    def f = macro fImpl
    
    scala> f
    <empty>
    
    scala> implicit def aaa(a: String) = 5
    warning: there was one feature warning; re-run with -feature for details
    aaa: (a: String)Int
    
    scala> "A" : Int
    res10: Int = 5
    
    scala> f
    {
      ((a: String) => $line47.$read.$iw.$iw.$iw.$iw.$iw.$iw.aaa(a))
    }
    

    如果silent参数为false(默认情况下为true),则在推断错误的情况下将抛出TypecheckException。因此,您可以对其进行分析,以找到含糊不清的隐式列表。

    P.S.如果B类型未知-没有(记录的)使用宏来查找所有隐式的方法:openImplicits/enclosingImplicits只是寻找在宏扩展的上下文中实现的隐式-并非全部存在于上下文中。编译器插件可能会有所帮助,但这并不是那么容易。

    如果您真的决定尝试“编译器插件”方式-查找隐式逻辑的实现是hereHere,您可以找到编译器的Context(与宏的不同)及其implicitss字段,该字段包含上下文中的所有隐式内容(但获取适当的上下文并不是那么简单)。

    而且我不应该告诉您,但是有一个棘手且不安全的技巧可以将宏Context提升到编译器级别并执行您想要的操作:
     scala>  def fImpl(c: Context): c.Expr[Unit] = {
     |       val cc = c.asInstanceOf[reflect.macros.contexts.Context]
     |       println(cc.callsiteTyper.context.implicitss.flatten)
     |       c.universe.reify( () )
     |  }
    fImpl: (c: reflect.macros.Context)c.Expr[Unit]
    
    scala> def f = macro fImpl
    
    scala> f //I've defined aaaaaaaa etc. implicits while playing with that
    List(aaaaaaaa: ?, lllllllllllllllllllllzzzz: ?, lllllllllllllllllllll: ?, lllllllllllllllllllll: ?, aaa: ?, aaa: ?, aaa: ?, aaa: ?, aaa: ?, aaa: ?, b: ?, a: ?, macros: ?, RuntimeClassTag:
    

    无论如何,您必须对 ImplicitInfo 列表进行分析以获得所需的隐式内容,从 Analizer 的来源可以看出,它可能并不琐碎,但至少有可能获得近似结果,这可能对您的需求。但是同样,最好还是非常小心地进行,因为您使用的结构是可变的,并且方法不是纯净的。而且,正如@Eugene Burmako注意到的那样,此解决方案不会为您提供伴随对象的隐式。

    关于scala - 在宏上下文中查找隐式方法定义,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29834187/

    10-11 22:49
    查看更多