如何从宏中看到符号的定义?
作为一个特殊情况,我想知道如何在编译时使用宏计算常量值。我的方法适用于"final val",但不适用于局部"val":
// scalaVersion := "2.11.0"
import scala.reflect.macros.blackbox.Context
import scala.language.experimental.macros
object Const {
def m_same(c: Context)(i: c.Tree) = {
import c.universe._
val Literal(Constant(_)) = i
i
}
def same(i: Any): Any = macro m_same
}
本地值不能被识别为Literal(Constant(_))
:
import org.scalatest.FreeSpec
class ConstSpec extends FreeSpec {
"Int literal" in {
assert(Const.same(42) === 42)
}
final val iFinal = "mytest" // is a Literal(Constant(_))
"final Int value" in {
assert(Const.same(iFinal) === iFinal)
}
"local Int value" in {
val iLocal = 42 // is NOT a Literal(Constant(_))
assert(Const.same(iLocal) === iLocal) // does NOT compile
}
}
final val
对常量有特殊意义,意味着将它们内联。
您的普通val看起来像:
scala> q"{ val i = 42 ; i }"
res0: reflect.runtime.universe.Tree =
{
val i = 42;
i
}
scala> showRaw(res0)
res1: String = Block(List(ValDef(Modifiers(), TermName("i"), TypeTree(), Literal(Constant(42)))), Ident(TermName("i")))
我认为Travis Brown的metapplasm博客,也就是你不应该在家里尝试使用宏的事情,包括检查周围的上下文。
在这种情况下,在语句的基础上查询封闭上下文将发现您想要的i
的def,并且可以检查它的RHS。
他们的宏观理念是本地化思考,本地化扩张。这是我瞎编的。它们还为同伴等非本地的东西提供宏注释。
但是等等,他们确实在Context
上提供了eval
设施。这对您的用例来说足够了吗?