MethodSymbol
をScala 2.10のメソッド定義ツリー(DefDef
)の左側にするのに便利な方法はありますか?メソッドシンボルとボディからメソッド定義ツリーを作成する
たとえば、特性のインスタンスを取り、その特性のすべてのメソッドをいくつかのデバッグ機能でラップするマクロを作成するとします。私は、次のように記述することができます。
import scala.language.experimental.macros
import scala.reflect.macros.Context
object WrapperExample {
def wrap[A](a: A): A = macro wrap_impl[A]
def wrap_impl[A: c.WeakTypeTag](c: Context)(a: c.Expr[A]) = {
import c.universe._
val wrapped = weakTypeOf[A]
val f = Select(reify(Predef).tree, "println")
val methods = wrapped.declarations.collect {
case m: MethodSymbol if !m.isConstructor => DefDef(
Modifiers(Flag.OVERRIDE),
m.name,
Nil, Nil,
TypeTree(),
Block(
Apply(f, c.literal("Calling: " + m.name.decoded).tree :: Nil),
Select(a.tree, m.name)
)
)
}.toList
//...
}
私は形質を実装する新しい匿名クラスでこれらのメソッドをこだわりの退屈な業務を省かきたし、そのクラス-あなたのインスタンスを作成すると、「あなたの場合、完全な作業例hereを見つけることができます興味がある。
今私は、たとえば、これを書くことができます。
scala> trait X { def foo = 1; def bar = 'a }
defined trait X
scala> val x = new X {}
x: X = [email protected]
scala> val w: X = WrapperExample.wrap[X](x)
w: X = [email protected]
scala> w.foo
Calling: foo
res0: Int = 1
scala> w.bar
Calling: bar
res1: Symbol = 'a
をだから、それは動作しますが、形質がアクセス修飾子、注釈付きパラメータリストを持つメソッドを持っている場合にのみ、非常に簡単に例 - それはないだろう、
私が本当に望むのは、新しいボディにメソッドシンボルとツリーをとり、DefDef
を返す関数です。私は手で1書き始めましたが、それはこのように手間のかかるものの多くが含ま:、迷惑な冗長、およびエラーが発生しやすい
List(if (method.isImplicit) Some(Flag.IMPLICIT) else None, ...)
。新しいReflection APIでこれを行うには、より良い方法がいくつかありますか?
ありがとう(と+1)、私がラップしようとしている特性がライブラリからのものなら、どうすればよいでしょうか?その場合、私は上記のアプローチに悩まされています。 –
ああ、私はあなたが意味するものを参照してください。このAPIはhttps://github.com/scalamacros/kepler/blob/0acb8a30c379f268e8a3e1340504530493a1a1dc/src/reflect/scala/reflect/api/Trees.scala#L2480で使用できます。 2.10.1で廃止されましたが、実装方法についてはhttps://github.com/scalamacros/kepler/blob/0acb8a30c379f268e8a3e1340504530493a1a1dc/src/reflect/scala/reflect/internal/Trees.scala#L975をご覧ください。 。 –