Bu, benim previous question numaralı telefonumda bir takiptir.Oluşturulan makro yöntemindeki `this` işlevini kullanın.
Aşağıdaki kodun çalışmasını istiyorum. Bir makro oluşturulan yöntem oluşturmak mümkün istiyorum:
case class Cat()
test[Cat].method(1)
Nerede kendisi bir makro (a "vampire" method) kullanıyor üretilen yöntemin uygulanması:
// macro call
def test[T] = macro testImpl[T]
// macro implementation
def testImpl[T : c.WeakTypeTag](c: Context): c.Expr[Any] = {
import c.universe._
val className = newTypeName("Test")
// IS IT POSSIBLE TO CALL `otherMethod` HERE?
val bodyInstance = q"(p: Int) => otherMethod(p * 2)"
c.Expr { q"""
class $className {
protected val aValue = 1
@body($bodyInstance)
def method(p: Int): Int = macro methodImpl[Int]
def otherMethod(p: Int): Int = p
}
new $className {}
"""}
}
// method implementation
def methodImpl[F](c: Context)(p: c.Expr[F]): c.Expr[F] = {
import c.universe._
val field = c.macroApplication.symbol
val bodyAnnotation = field.annotations.filter(_.tpe <:< typeOf[body]).head
c.Expr(q"${bodyAnnotation.scalaArgs.head}.apply(${p.tree.duplicate})")
}
Bu kod ile derlenmeyecektir :
[error] no-symbol does not have an owner
last tree to typer: This(anonymous class $anonfun)
[error] symbol: anonymous class $anonfun (flags: final <synthetic>)
[error] symbol definition: final class $anonfun extends AbstractFunction1$mcII$sp with Serializable
[error] tpe: examples.MacroMatcherSpec.Test.$anonfun.type
[error] symbol owners: anonymous class $anonfun -> value <local Test> -> class Test -> method e1 -> class MacroMatcherSpec -> package examples
[error] context owners: value $outer -> anonymous class $anonfun -> value <local Test> -> class Test -> method e1 -> class MacroMatcherSpec -> package examples
[error]
[error] == Enclosing template or block ==
[error]
[error] DefDef(// val $outer(): Test.this.type
[error] <method> <synthetic> <stable> <expandedname>
[error] "examples$MacroMatcherSpec$Test$$anonfun$$$outer"
[error] []
[error] List(Nil)
[error] <tpt> // tree.tpe=Any
[error] $anonfun.this."$outer " // private[this] val $outer: Test.this.type, tree.tpe=Test.this.type
[error])
bunun ne anlama geldiğini deşifre de çok kötü ama ben gövdesinde this.otherMethod
başvuramaz gerçeği ile ilişkili olduğunu sanıyorum vampir yöntemi. Bunu yapmanın bir yolu var mı? Bu çalışırsa
, sonraki adımım otherMethod
için uygulama bu tür olacaktır:
def otherMethod(p: Int) = new $className {
override protected val aValue = p
}
gibi bir şey ben sadece [bir blog post] (http://meta.plasm.us/posts/2013/08/31/feeding- olarak bu soruna daha genel bir yanıt yazdık bizim-vampirler /). Eğer aradığınız şey varsa, yoğunlaştırılmış bir sürümü burada bir cevap olarak ekleyebilirim. –