Scala中的宏访问参数值时,编译问题(Compilation issue when accessi

2019-10-18 13:45发布

这个小例子,调用代码看起来编译(Eclipse的靛蓝SR2,斯卡拉v2.10.20),但包含调用代码项目标有红色的叉号(我不清楚如何获得进一步诊断此)。 无级文件生成。 如果我有一些文字比如1代替param.value,调用代码编译。

这是一个已知的问题? 有没有解决办法?

def myMacro( param : Int ): Int = macro myMacroImpl( param )

def myMacroImpl(c: Context)(param: c.Expr[Int]): c.Expr[Int] = {
    import c.universe._

    c.Expr( Literal( Constant( param.value ) ) )         
}

Answer 1:

首先,宏定义的语法并不需要(或允许)您指定的参数宏的实现方法,使你的代码不应该编译,即使在实现文字。 见下面的正确的语法我的例子。

接下来, Expr.value是不幸的是谎言。 回想一下参数给宏方法是可变的情况。 该变量的值是不是(在一般情况下不能 )在编译时已知的,但你试图与该值的编译时间常量。 它只是从根本行不通的。

你有几个选项,这取决于你想做什么可能或可能不适用。 假设我们需要添加一个到param值,并返回结果,例如。 如果我们想加入在编译时发生,我们不得不抛出一个(编译时)的异常时,我们没有得到一个编译时的文字:

def myMacro(param: Int): Int = macro myMacroImpl

def myMacroImpl(c: Context)(param: c.Expr[Int]): c.Expr[Int] = {
  import c.universe._

  val p = param.tree match {
    case Literal(Constant(p: Int)) => p
    case _ => c.abort(c.enclosingPosition, "param must be a literal value!")
  }

  c.literal(p + 1) // Or, equivalently: c.Expr(Literal(Constant(p + 1))
}

另一种选择是围绕打造一棵树param表达。 例如,下文中也将返回后继param ,但在运行时执行相加,并且该方法可以处理非文字形参:

def myMacro(param: Int): Int = macro myMacroImpl

def myMacroImpl(c: Context)(param: c.Expr[Int]): c.Expr[Int] = {
  import c.universe._

  c.Expr(
    Apply(Select(param.tree, newTermName("$plus")), c.literal(1).tree :: Nil)
  )
}

我们只是不会得到编译时除了和任意param表达,虽然。



文章来源: Compilation issue when accessing parameter value in Scala macro