【发布时间】:2017-03-12 06:13:18
【问题描述】:
隐式宏的用例应该是类型类实例的所谓“物化”。
不幸的是,documentation 中的示例对于如何实现有点模糊。
在被调用时,物化器可以获取 T 的表示并生成 Showable 类型类的适当实例。
假设我有以下特征......
trait PrettyPrinter[T]{
def printed(x:T) : String
}
object PrettyPrinter{
def pretty[T](x:T)(implicit pretty:PrettyPrinter[T]) = pretty printed x
implicit def prettyList[T](implicit pretty :PrettyPrinter[T]) = new PrettyPrinter[List[T]] {
def printed(x:List[T]) = x.map(pretty.printed).mkString("List(",", ",")")
}
}
和三个测试类
class A(val x:Int)
class B(val x:Int)
class C(val x:Int)
现在我明白了,而不是编写以下样板
implicit def aPrinter = new PrettyPrinter[A] {def printed(a:A) = s"A(${a.x})"}
implicit def bPrinter = new PrettyPrinter[B] {def printed(b:B) = s"B(${b.x})"}
implicit def cPrinter = new PrettyPrinter[C] {def printed(c:C) = s"C(${c.x})"}
我们应该可以添加
implicit def materialise[T] : PrettyPrinter[T] = macro implMaterialise[T]
def implMaterialise[T](c:blackbox.Context):c.Expr[PrettyPrinter[T]] = {
import c.universe._
???
}
到object PrettyPrinter{...},然后根据需要生成相应的PrettyPrinters ...如何?我如何真正获得“T 的表示”?
如果我尝试c.typeOf[T],例如,“没有可用于 T 的 TypeTag”。
更新
尝试使用类标签似乎也不起作用。
implicit def materialise[T:ClassTag] : PrettyPrinter[T] = macro implMaterialise[T]
def implMaterialise[T:ClassTag](c:blackbox.Context):c.Expr[PrettyPrinter[T]] = {
import c.universe._
???
}
结果
Error:(17, 69) macro implementations cannot have implicit parameters other than WeakTypeTag evidences
implicit def materialise[T:ClassTag] : PrettyPrinter[T] = macro implMaterialise[T]
^
更新2
有趣的是,使用 WeakTypeTags 并没有真正改变任何东西
implicit def materialise[T:WeakTypeTag]: PrettyPrinter[T] = macro implMaterialise[T]
def implMaterialise[T](c:blackbox.Context)(implicit evidence : WeakTypeTag[T]):c.Expr[PrettyPrinter[T]]
= {
import c.universe._
???
}
将导致
Error:(18, 71) macro implementations cannot have implicit parameters other than WeakTypeTag evidences
implicit def materialise[T:WeakTypeTag]: PrettyPrinter[T] = macro implMaterialise[T]
^
【问题讨论】:
-
这里不需要宏。它应该只适用于
PrettyPrinter.pretty(List(A(2))) -
@Reactormonk 感谢您的评论。但是,不会因为
pretty找不到PrettyPrinter[A]的实例。如果您想在评论之前阅读问题,您会注意到使用宏的目的是避免编写样板代码,为每个类定义一个PrettyPrinter。您还会注意到,我对替代的非宏解决方案(如果存在)不感兴趣,因为我提出这个问题是为了更好地理解宏文档中的用例。 -
T: TypeTag- shapeless 使用宏,您可以查看这些用于泛型派生。 -
@Reactormonk 我看不出这有什么帮助。他们只是匹配一个 AST 节点并检查它是否是他们期望的......这与我正在尝试的相反。也许您可以告诉我如何在上面的宏中为
T获取类型标记(或任何可以让我访问类符号)? (见更新)
标签: scala macros implicit-conversion implicit