更新:我怀疑我想要的可能是不可能的,我已经写了一篇博客文章,其中包含我的推理(和一些替代方案)here。我会很高兴被告知我错了。
假设我想使用带有宏实现的工厂方法创建特征的实例。这个方法将把一个资源的路径作为参数,宏将读取和解析(在编译时)从字符串到字符串的映射。
那部分都很简单。现在假设我想将生成的映射与我正在创建的实例相关联,以便我可以在涉及该实例的后续宏调用中使用它。
我非常不希望地图成为实例的成员,或者在运行时以任何形式存在。我也不想多次解析同一个资源。这是我要实现的目标的草图:
import scala.language.experimental.macros
import scala.reflect.macros.Context
trait Foo {
def lookup(key: String): String = macro Foo.lookup_impl
}
object Foo {
def parseResource(path: String): Map[String, String] = ???
def apply(path: String): Foo = macro apply_impl
def apply_impl(c: Context)(path: c.Expr[String]): c.Expr[Foo] = {
import c.universe._
val m = path.tree match {
case Literal(Constant(s: String)) => parseResource(s)
}
val tree = reify(new Foo {}).tree
// Somehow associate the map with this tree here.
c.Expr(tree)
}
def lookup_impl(c: Context)(key: c.Expr[String]): c.Expr[String] =
/* Somehow read off the map and look up this key. */ ???
}
这似乎是附件旨在帮助解决的事情(感谢Eugene Burmako的指针),我有一个基于附件的实现,允许我编写以下内容:
Foo("whatever.txt").lookup("x")
Whereapply_impl
将地图附加到树上并lookup_impl
从同一棵树中读取该附件,并将其视为其前缀。不幸的是,这或多或少没用,因为它foo.lookup("x")
在前缀树只是变量的情况下不起作用foo
。
(请注意,在我的实际用例中Foo
extends Dynamic
,并且我试图为selectDynamic
而不是提供宏实现lookup
,但这在这里不应该相关 - 我对一般情况感兴趣。)
有什么方法可以让我使用附件来获得我想要的东西吗?还有其他更合适的方法吗?