MethodSymbol
'u Scala 2.10'da bir yöntem tanımlama ağacının (ör. DefDef
) sol tarafına döndürmenin kullanışlı bir yolu var mı? Örneğin, bir özelliğin bir örneğini alacak ve bu tüm trait yöntemlerini bazı hata ayıklama işlevleri ile dolduracak bir makro oluşturmak istediğimi varsayalım. Yazabilirim aşağıdaki: Ben özelliği uygulayan yeni bir anonim sınıfta bu yöntemleri yapışmasını ve daha sonra bu sınıf-sen eğer tam bir çalışma örneği here bulabilirsiniz nesnelleştirilme sıkıcı iş elided ettikBir yöntem sembolünden ve bir gövdeden bir yöntem tanımlama ağacı oluşturma
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
//...
}
' ilgileniyorum.
Şimdi örneğin, bu yazabilirsiniz:
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
Yani çalışıyor, ama sadece çok basit durumlarda-o alışkanlık özelliği erişim değiştiricileri, ek açıklamalarla parametre listeleri ile yöntemlerini, varsa,
Gerçekten istediğim bir yöntem sembolü ve yeni gövde için bir ağaç alacak ve bir DefDef
döndürecektir. Ben elle tek yazmaya başladım, ama böyle keman bir sürü içerir: can sıkıcı ayrıntılı ve hataya açık olan
List(if (method.isImplicit) Some(Flag.IMPLICIT) else None, ...)
. Yeni Yansıma API'sinde bunu yapmanın daha güzel bir yolunu mu duyuyorum?
Teşekkürler (ve +1), ama sarmak istediğim özellik kütüphaneden mi geliyor? Bu durumda, yukarıdaki yaklaşıma takıldım, değil mi? –
Ah Ne demek istediğini görüyorum. Bu API'yi kullanabilirsiniz: https://github.com/scalamacros/kepler/blob/0acb8a30c379f268e8a3e1340504530493a1a1dc/src/reflect/scala/reflect/api/Trees.scala#L2480. 2.10.1'de kullanımdan kaldırdık, ancak nasıl uygulandığına göz atabilirsiniz: https://github.com/scalamacros/kepler/blob/0acb8a30c379f268e8a3e1340504530493a1a1dc/src/reflect/scala/reflect/internal/Trees.scala#L975 . –