Макрос scala со свежим идентификатором

У меня есть макрос, который я хочу использовать для регистрации времени, которое требуется для выполнения блока, который может вернуть что-то полезное. Так что, если у меня есть что-то вроде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
  }
}

1 ответ

Вы не хотите TermNameхочешь Ident:

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

Но если имя идентификатора является константой, нет никаких оснований даже создавать такой идентификатор, когда вы могли бы просто написать:

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

Изменение, которое исправит эту проблему, но есть и другие. t0 не определено в квазицитатах, а все остальные имена терминов, которые вы определили, на самом деле ничего не делают.

Я не понимаю, зачем вам нужен макрос для этого, когда обычный метод отлично справляется со своей задачей. Макрос увеличит размер вашего кода (значительно, если вы будете его часто использовать).

Другие вопросы по тегам