Макрос 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
не определено в квазицитатах, а все остальные имена терминов, которые вы определили, на самом деле ничего не делают.
Я не понимаю, зачем вам нужен макрос для этого, когда обычный метод отлично справляется со своей задачей. Макрос увеличит размер вашего кода (значительно, если вы будете его часто использовать).