我是不是能夠直接重用withSource
只是打印源和值,並返回值。該withSource
宏不能從同一個對象本身使用的(所以我不能只是添加我withSource的略加修改就在該文件),我不能夠調用withSource
從WithSourceHelper
一個子類,通過繼承限制重用。
如果有人有興趣,這裏是一個補充塞尼亞的答案,只需登錄與源的值,並返回值,因此計算的其餘部分可發生。
def logValueImpl[T](c: Context): c.Expr[T] = {
import c.universe._
val source = c.prefix.tree match {
case Apply(_, List(s)) => s
case _ => c.abort(c.enclosingPosition, "can't find source")
}
val freshName = newTermName(c.fresh("logValue$"))
val valDef = ValDef(Modifiers(), freshName, TypeTree(source.tpe), source)
val ident = Ident(freshName)
val print = reify{
println(c.literal(show(source)).splice + ": " + c.Expr[T](ident).splice) }
c.Expr[T](Block(List(valDef, print.tree), ident))
}
然後,我將其定義爲def p = macro Debug.logValueImpl[T]
上的隱式轉換。然後我可以使用這樣的:
List(1, 2, 3).reverse.p.head
// prints: immutable.this.List.apply[Int](1, 2, 3).reverse: List(3, 2, 1)
有趣的是,我可以申請兩次:
List(1, 2, 3).reverse.p.p
,它會告訴我logValueImpl
宏做了什麼:
{
val logValue$7: List[Int] = immutable.this.List.apply[Int](1, 2, 3).reverse;
Predef.println("immutable.this.List.apply[Int](1, 2, 3).reverse: ".+(logValue$7));
logValue$7
}
這似乎與其它宏以及工作:
f"float ${1.3f}%3.2f; str ${"foo".reverse}%s%n".p`
//prints:
{
val arg$1: Float = 1.3;
val arg$2: Any = scala.this.Predef.augmentString("foo").reverse;
scala.this.Predef.augmentString("float %3.2f; str %s%%n").format(arg$1, arg$2)
}: float 1.30; str oof%n
更有趣的是,如果我用showRaw
代替show
我甚至可以看到擴展的宏,這可能會派上用場弄清楚如何寫其他宏樹。
我剛剛發現有類似的功能(及以上)在以下庫中:https://github.com/retronym/macrocosm;看'log','trace','desugar' ... – huynhjl