Đây là lần theo dõi trên previous question của tôi.Sử dụng 'this` trong phương thức macro được tạo
Tôi muốn một cái gì đó giống như mã bên dưới để hoạt động. Tôi muốn để có thể tạo ra một phương pháp vĩ mô tạo:
case class Cat()
test[Cat].method(1)
Trường hợp thực hiện của phương pháp tạo ra bản thân đang sử dụng một macro (một "vampire" method):
// 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})")
}
Mã này thất bại trong việc biên dịch với :
[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])
tôi thực sự xấu tại giải mã điều này có nghĩa nhưng tôi nghi ngờ rằng nó có liên quan đến thực tế là tôi không thể tham khảo this.otherMethod
trong cơ thể của phương pháp ma cà rồng. Có cách nào làm được việc này không?
Nếu công trình này, bước tiếp theo của tôi sẽ có loại triển khai cho otherMethod
:
def otherMethod(p: Int) = new $className {
override protected val aValue = p
}
Tôi vừa mới viết một câu trả lời chung hơn cho vấn đề này là [bài đăng trên blog] (http://meta.plasm.us/posts/2013/08/31/feeding- ma cà rồng của chúng tôi /). Tôi có thể thêm một phiên bản ngưng tụ như là một câu trả lời ở đây nếu đó là những gì bạn đang tìm kiếm. –