访问符号的定义主体

时间:2014-05-07 22:48:19

标签: scala reflection macros scala-macros

如何从宏中查看符号的定义?

作为一个特例,我想知道如何使用宏在编译时评估常量值。 我的方法适用于" 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
  }
}

1 个答案:

答案 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设施。这对你的用例来说是否足够?