我正在将一些代码从 Scala 2.10-M5迁移到 Scala 2.10-M7。我发现宏上下文中的 Type API 已显着减少。特别是,我想知道如何获得底层和typeArgs defs。
--
更新
按照@EugeneBurmako 的要求,我将展示整个画面。假设我们有这个状态:
class Attribute[C[_], E]
class Id[E]
trait Entity {
val att1: List[Int]
val att2: Int
}
object Entity {
val att1reif = new Attribute[List, Int]
val att2reif = new Attribute[Id, Int]
}
def Let[T <: Entity, C[_], E](en: T, att: Attribute[C, E], ce: C[E]): T =
/* Updates the whole attribute */
def Let[T <: Entity, C[_], E](en: Entity, att: Attribute[C, E], e: E, mode: Boolean): T =
/* Adds or removes (mode) an item */
我们有一个实体托管一些属性。实体伴随对象包含有关这些属性的元信息(具体化)。Let系列允许更新实体(通过创建新副本)。
到现在为止还挺好。我们可以使用 Let 方法如下:
val ent = new Entity { val att1 = List(); val att2 = 3 }
Let(ent, Entity.att1reif, List(1, 2, 3)) // att1 = List(1, 2, 3)
Let(ent, Entity.att1reif, 4, true) // att1 = List(1, 2, 3, 4)
Let(ent, Entity.att1reif, 1, false) // att1 = List(2, 3, 4)
reification 属性是多余的,所以我们希望我们的用户有一个更简单的 API。特别是下一个:
// Same code as DSL
ent.att1 := List(1, 2, 3)
ent.att1 :+ 4
ent.att1 :- 1
请注意,任何地方都没有关于具体化的信息。因此,我们需要一些Helpers和一个宏观视图来实现我们的目标。
trait AttributeHelper {
type T <: Entity
type C[_]
type E
val ent: T
val att: Attribute[C, E]
def :=(ce: C[E]): T = Let(ent, att, ce)
def :+(e: E): T = Let(ent, att, e, true)
def :-(e: E): T = Let(ent, att, e, false)
}
def toAttributeHelperImpl[V: c.AbsTypeTag](c: Context)(expr: c.Expr[V]): c.Expr[AttributeHelper] =
/* A looong macro (currently broken), since I can't split V into C[_] and E,
* which are needed to generate the expression that instantiates an *AttributeHelper*.
* The macro is responsible of finding the attribute reification.
*/
事实上,我们的宏定义是一个视图,它神奇地允许 DSL 表达式:
implicit def toAttributeHelper[V](expr: V): AttributeHelper = macro toAttributeHelperImpl[V]
我一直在尝试使用使用两种类型参数的宏,但是这样做时,不应用隐式视图(因为编译器无法推断这两种类型)。
因此,正如我在开头提到的那样, M5 中没有typeArgs,但 M7 中没有,这破坏了之前的宏。如何在没有该定义的情况下生成 AttributeHelper 构造?
最后,我必须说,前面的代码只是一个简化。还有一些其他涉及的证据,这就是为什么我需要使用底层的.