2013-03-27 35 views
3

我想在selectDynamic的以下宏实现中使用Sample#cap(String)在selectDynamic的宏实现中调用实例方法

可能吗?

// macro implementation 
import scala.language.experimental.macros 
import scala.reflect.macros._ 

object MyMacros { 
    def selectDynamic(c: Context)(name: c.Expr[String]): c.Expr[String] = { 
    // I expected `This` to refer a Sample instance, but actually it refers SampleSpec instance... 
    c.Expr[String](Apply(TypeApply(Select(This(tpnme.EMPTY), newTermName("cap")), List(Ident(typeTag[String].tpe.typeSymbol))), List(name.tree))) 
    } 
} 

// class which uses selectDynamic and macro 
import scala.language.dynamics 
class Sample extends Dynamic { 
    def cap(name: String): String = name.toUpperCase 
    def selectDynamic(name: String): String = macro MyMacros.selectDynamic 
} 

class SampleSpec extends FlatSpec with ShouldMatchers { 
    it should "call dynamic" in { 
    val sample = new Sample 
    sample.foo should equal("FOO") // value cap is not a member of SampleSpec 
    } 
} 

回答

6

您可以使用c.prefix.tree而不是This

// macro implementation 
import scala.language.experimental.macros 
import scala.reflect.macros.Context 
import language.dynamics 

object MyMacros { 
    def selectDynamic(c: Context)(name: c.Expr[String]): c.Expr[String] = { 
    import c.universe._ 
    // I expected `This` to refer a Sample instance, but actually it refers SampleSpec instance... 
    c.Expr[String](Apply(Select(c.prefix.tree, newTermName("cap")), List(name.tree))) 
    } 
} 

// class which uses selectDynamic and macro 
class Sample extends Dynamic { 
    def cap(name: String): String = name.toUpperCase 
    def selectDynamic(name: String): String = macro MyMacros.selectDynamic 
} 
+0

太棒了!你一直很有帮助。非常感谢。 – 2013-03-27 09:51:27