如何从宏中查看符号的定义?
作为一个特例,我想知道如何使用宏在编译时评估常量值。 我的方法适用于" 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
}
}
答案 0 :(得分:1)
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")))
我认为特拉维斯·布朗的Metaplasm博客,即你不应该在家里尝试宏的事情,包括检查def的周围环境。
在这种情况下,在声明的基础上查询封闭的上下文会发现你想要的i
的def,你可以检查它的RHS。
他们的宏观哲学是思考本地和扩展本地。我刚刚做到了。它们还为同伴之类的本地事物提供宏观注释。
但等等,他们确实在eval
上提供Context
设施。这对你的用例来说是否足够?