我了解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
只是寻找在宏扩展的上下文中实现的隐式-并非全部存在于上下文中。编译器插件可能会有所帮助,但这并不是那么容易。如果您真的决定尝试“编译器插件”方式-查找隐式逻辑的实现是here。 Here,您可以找到编译器的
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/