如何从M7中的类型获取typeArgs?

时间:2012-09-24 13:49:39

标签: scala reflection macros scala-2.10

我正在将一些代码从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 */

我们有实体托管一些属性。实体伴随对象包含有关这些属性的元信息(reifications)。 系列允许更新实体(通过创建新副本)。

到目前为止,这么好。我们可以使用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

请注意,任何地方都没有关于具体化的信息。因此,我们需要一些助手和宏观视图来实现我们的目标。

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中没有,已经打破了以前的宏。如何在没有def?

的情况下生成AttributeHelper构造

最后,我必须说前面的代码只是一个简化。还有一些其他涉及的证据,这就是我需要使用底层的原因。

1 个答案:

答案 0 :(得分:2)

在M5周围发生的反射API清理背后的一般想法是删除非常专业的方法。

例如,typeArgs仅适用于TypeRef类型,因此将其保留在基本类型Type中没有多大意义。替换是一种简单的模式匹配:tpe match { case TypeRef(_, _, args) => arg; case _ => Nil }

但是,

underlying是不同的,因为它是一个内部实现概念,意味着很多东西取决于类型的具体风格。如果您详细说明您的用例,我可能会帮助您找到underlying的替代方案。