【问题标题】:scala macro with fresh identifier具有新标识符的 scala 宏
【发布时间】:2016-04-14 10:25:56
【问题描述】:

我有一个宏,我想用它来记录执行一个可能返回有用信息的块所需的时间。所以如果我有类似的东西 val y = f(x)我会改成val y = Timed(f(x))来获取日志中函数的执行时间。

我几乎有我想要的,但是当使用新的术语名称以避免名称冲突时,例如在 t0 和 t1 之间,我收到一个错误:

Error:(22, 15) Can't unquote reflect.runtime.universe.TermName, consider providing an implicit instance of Liftable[reflect.runtime.universe.TermName]
         val $kk = System.nanoTime()
          ^

如何让这些freshTermNames 与准引号一起使用?

import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context
import scala.reflect.runtime.{ universe ⇒ u }

object Timed {
  def apply[T](block: ⇒ T): T = macro Timed.apply_impl[T]

  def apply_impl[T: c.WeakTypeTag](c: Context)(block: c.Expr[T]): c.Expr[T] = {
    import c.universe._
    implicit val cc: c.type = c
    val kk = u.internal.reificationSupport.freshTermName("kk")
    val t0 = c.freshName("t0")
    val t1 = c.freshName("t1")
    val tdiff = c.freshName("tdiff")
    val blk = c.freshName("blk")
    val t0n = "t0"
    println(t0)
    val res = c.Expr(
      q"""
         val $kk = System.nanoTime()
         $block
         val t1 = System.nanoTime()
         val tdiff= t1 - t0
         log.debug("Took: {}", tdiff)
         $block
       """)
    println("Timing block: ")
    println(show(res))
    res
  }
}

【问题讨论】:

    标签: scala macros scala-quasiquotes


    【解决方案1】:

    你不想要TermName,你想要Ident

    val kk = Ident(TermName("kk"))
    

    但是,如果标识符的名称是常量,那么甚至没有理由像这样构造标识符,而您本来可以这样写:

    q"""
       val kk = System.nanoTime
       ...
    """
    

    改变它会解决这个问题,但还有其他问题。 t0 在准引号中未定义,您定义的所有其他术语名称实际上都没有任何作用。

    我不明白为什么你需要一个宏来做这个,或者,当一个普通的方法做得很好时。该宏会增加代码的大小(如果您经常使用它,则显着增加)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-25
      • 1970-01-01
      • 2011-12-01
      • 2015-02-09
      • 2016-03-28
      • 1970-01-01
      相关资源
      最近更新 更多