Scala宏中按名称处理参数

Scala宏中按名称处理参数,scala,scala-macros,callbyname,Scala,Scala Macros,Callbyname,我有一个宏,可以对嵌套函数应用程序进行一些分析。它通过以下方式匹配应用程序并检索参数类型: case q"$f[..$targs](..$args)(...$otherArgs)" => // retrieve the list of all parameter types val paramTpes = f.tpe match { case pmt: PolyType if pmt.paramLists.size == 0 => Seq

我有一个宏,可以对嵌套函数应用程序进行一些分析。它通过以下方式匹配应用程序并检索参数类型:

case q"$f[..$targs](..$args)(...$otherArgs)" =>

    // retrieve the list of all parameter types
    val paramTpes = f.tpe match {
      case pmt: PolyType if pmt.paramLists.size == 0 =>
        Seq()
      case pmt: PolyType =>
        pmt.paramLists(0) map {_.typeSignature
             .substituteTypes(pmt.typeParams, targs map (_.tpe))}
      case pmt: MethodType if pmt.paramLists.size == 0 =>
        Seq()
      case pmt: MethodType =>
        pmt.paramLists(0) map (_.typeSignature)
    }
现在,如果碰巧有按名称的参数,我得到的是一些奇怪的类型,它打印出
=>T
,但不能与任何东西匹配。反射API中似乎没有适当处理这些问题的工具。
我想做的是检索
T
,以防它是
=>T
,因为
=>T
会在生成的代码中引起进一步的问题。

通常,使用提取器。有时我必须了解运行时类是什么,以记住要使用的提取器。我不是每天都使用API

scala> import reflect.runtime._, universe._
import reflect.runtime._
import universe._

scala> class X { def x(i: => Int) = i * 2 }
defined class X

scala> typeOf[X].member(TermName("x"))
res0: reflect.runtime.universe.Symbol = method x

scala> .typeSignature
res1: reflect.runtime.universe.Type = (i: => scala.Int)scala.Int

scala> res1 match { case MethodType(ps, res) => ps }
res2: List[reflect.runtime.universe.Symbol] = List(value i)

scala> .head
res3: reflect.runtime.universe.Symbol = value i

scala> .typeSignature
res4: reflect.runtime.universe.Type = => scala.Int

scala> res4.getClass
res5: Class[_ <: reflect.runtime.universe.Type] = class scala.reflect.internal.Types$ClassArgsTypeRef

scala> res4 match { case TypeRef(pre, sym, args) => sym }
res6: reflect.runtime.universe.Symbol = class <byname>

scala> res4 match { case TypeRef(pre, sym, args) => args }
res7: List[reflect.runtime.universe.Type] = List(scala.Int)

scala> definitions
res8: reflect.runtime.universe.DefinitionsApi = scala.reflect.internal.Definitions$definitions$@4e80a001

scala> definitions.By
ByNameParamClass   ByteClass   ByteTpe

scala> definitions.ByNameParamClass
res9: reflect.runtime.universe.ClassSymbol = class <byname>
scala>import reflect.runtime.\uu,universe_
导入reflect.runtime_
导入宇宙_
scala>类X{defx(i:=>Int)=i*2}
定义类X
scala>typeOf[X]。成员(术语名称(“X”))
res0:reflect.runtime.universe.Symbol=方法x
scala>.typeSignature
res1:reflect.runtime.universe.Type=(i:=>scala.Int)scala.Int
scala>res1匹配{case MethodType(ps,res)=>ps}
res2:List[reflect.runtime.universe.Symbol]=List(值i)
scala>.head
res3:reflect.runtime.universe.Symbol=值i
scala>.typeSignature
res4:reflect.runtime.universe.Type==>scala.Int
scala>res4.getClass
res5:Class[res4 match{case TypeRef(pre,sym,args)=>sym}
res6:reflect.runtime.universe.Symbol=class
scala>res4匹配{case TypeRef(pre,sym,args)=>args}
res7:List[reflect.runtime.universe.Type]=List(scala.Int)
scala>定义
res8:reflect.runtime.universe.DefinitionsApi=scala.reflect.internal.Definitions$Definitions$@4e80a001
scala>definitions.By
ByNameParamClass ByteClass ByteType
scala>definitions.ByNameParamClass
res9:reflect.runtime.universe.ClassSymbol=class
我模模糊糊地记得这个特殊的名字,但我是否有一个稳定的前缀用于模式匹配?我想没有

scala> res4 match { case TypeRef(pre, definitions.ByNameParamClass, args) => args }
<console>:20: error: stable identifier required, but scala.reflect.runtime.`package`.universe.definitions.ByNameParamClass found.
 Note that method ByNameParamClass is not stable because its type, => reflect.runtime.universe.ClassSymbol, is volatile.
              res4 match { case TypeRef(pre, definitions.ByNameParamClass, args) => args }
                                                         ^

scala> val k = definitions.ByNameParamClass
k: reflect.runtime.universe.ClassSymbol = class <byname>

scala> res4 match { case TypeRef(pre, k, args) => args }
res11: List[reflect.runtime.universe.Type] = List(scala.Int)

scala> 
scala>res4 match{case TypeRef(pre,definitions.ByNameParamClass,args)=>args}
:20:错误:需要稳定标识符,但找到scala.reflect.runtime.`package`.universe.definitions.ByNameParamClass。
请注意,方法ByNameParamClass不稳定,因为其类型=>reflect.runtime.universe.ClassSymbol是易变的。
res4匹配{case TypeRef(pre,definitions.ByNameParamClass,args)=>args}
^
scala>val k=definitions.ByNameParamClass
k:reflect.runtime.universe.ClassSymbol=class
scala>res4匹配{case TypeRef(pre,k,args)=>args}
res11:List[reflect.runtime.universe.Type]=List(scala.Int)
斯卡拉>

谢谢,它使用了
c.universe.definitions.ByNameParamClass
。通过修改repl,我很快就找到了解决方案,但还没有找到!