在宏扩展中从前缀重新安装类型参数

Reinstalling type parameters from prefix in a macro expansion

下面应该显示问题:

class Container[A](val xs: List[A]) {
  def foo(fun: A => A)(implicit ord: Ordering[A]): List[A] =
    macro ContainerMacros.fooImpl // how to pass `xs`?
}

object ContainerMacros {
  def fooImpl(c: blackbox.Context)
             (fun: c.Expr[Nothing => Any])
             (ord: c.Expr[Ordering[_]]): c.Expr[List[Nothing]] = {
    import c.universe._
    reify {
      // val cont = c.prefix.splice.asInstanceOf[Container[_]]
      // cont.xs.map(fun.splice).sorted(ord.splice)
      ???
    }
  }
}

也就是说,似乎没有办法将 A 作为类型参数添加到 fooImpl (如果我这样做,编译器会抱怨)。所以我必须删除它,但问题是如何让 reify 中的内容按预期方式工作,即如何重新引入缺少的类型参数 A.

这是一次尝试:

def fooImpl(c: blackbox.Context)
           (fun: c.Expr[Nothing => Any])
           (ord: c.Expr[Ordering[_]]): c.Expr[List[Nothing]] = {
  import c.universe._
  reify {
    val ext   = c.prefix.splice.asInstanceOf[ExtensionTest[_]]
    import ext.{A1 => A}
    val extC  = ext       .asInstanceOf[ExtensionTest[A]]
    val funC  = fun.splice.asInstanceOf[A => A]
    val ordC  = ord.splice.asInstanceOf[Ordering[A]]
    val xs    = extC.xs.asInstanceOf[List[A]]   // computer says no
    xs.map(funC).sorted(ordC)
  }
}

xs.map(funC) 不适用于那些传奇的 scalac 错误消息之一:

Error:(27, 16) type mismatch;
 found   : _ => Any where type _
 required: Any => ?
        xs.map(funC).sorted(ordC)

实际上感谢@edmundnoble 通过 Scala Gitter 频道的回答:

您可以在 impl 调用中添加类型参数,因此可以将 AContainer 传递给宏扩展:

class Container[A](val xs: List[A]) {
  def foo(fun: A => A)(implicit ord: Ordering[A]): List[A] =
    macro ContainerMacros.fooImpl[A]
}

object ContainerMacros {
  def fooImpl[A](c: blackbox.Context)
                (fun: c.Expr[A => A])
                (ord: c.Expr[Ordering[A]])
                (implicit t: c.WeakTypeTag[A]): c.Expr[List[A]] = {
    import c.universe._
    reify {
      val extC  = c.prefix.splice.asInstanceOf[Container[A]]
      val funC  = fun.splice
      val ordC  = ord.splice
      val xs    = extC.xs
      xs.map(funC).sorted(ordC)
    }
  }
}