q“null”的类型是Literal,因此返回类型Expr [X]无效

时间:2015-03-08 20:56:21

标签: scala scala-macros

我有一个功能

def grammar(block: => Any): Grammar = macro grammarImpl

使用宏实现

def grammarImpl(c: Context)(block: c.Tree): c.Expr[Grammar] =
{
  q"null"
}

但我收到错误,输入不匹配;发现:c.universe.Literal required:c.Expr [Grammar](扩展为)c.universe.Expr [语法]

更换q" null"与c.literalNull然而编译好,我使用错误的quasiquote得到Null文字?

(Scala 2.11.6)

附带问题:我正在使用block:c.Tree,当我真的想要使用c.Expr [=>任何]。是否可以指定c.Expr [=>任何]类型?

1 个答案:

答案 0 :(得分:2)

你需要做

def grammarImpl(c: Context)(block: c.Tree): c.Expr[Grammar] =
  c.Expr[Grammar] {
    q"null"
  }

但是自scala 2.11(以下读取点9)以来,这已被弃用。

只需将返回类型更改为c.Tree即可完成:

def grammarImpl(c: Context)(block: c.Tree): c.Tree = q"null"

这是scala 2.11中引入的更改,您可以阅读它here

  

8)对宏实现签名的宽松要求。随着quasiquotes的出现,reify正在迅速成长,因为过于笨重和不灵活。要认识到我们现在允许两个参数和返回类型的宏实现都是c.Tree类型而不是c.Expr [Something]。不再需要编写大型签名,然后花费时间和代码行来尝试将宏实现与这些类型对齐。只需将树木带回来并将树木归还 - 样板就不见了。

     

9)宏定义类型的推断正在逐步取消。鉴于新的事物方案,宏实现可以返回c.Tree而不是c.Expr[Something],因此不再可能从宏impl的返回类型中稳健地推断宏defs的返回类型(如果宏impl返回{ {1}},然后该树的类型是什么?)。因此,我们正逐步取消这种语言机制。宏impls返回c.Tree仍可用于推断其宏defs的返回类型,但这将产生弃用警告,而尝试使用返回c.Expr[T]的宏impl来推断a的返回类型宏def将导致编译错误。