1

有没有办法为功能文字(2.11)制作一个可升降的?如果我有

case class Validator[T](predicate: T => Boolean)
val predicate = (s: String) => s.startsWith("Hi")

那么我也希望能够准引用predicate

q"new Validator($predicate)"

我希望神奇地创建一个带有下划线的 Liftable。但这有点太乐观了:

implicit def liftPredicate[T: Liftable](f: T => Boolean) = 
  Liftable[T => Boolean]{ f => q"$f(_)" }

通过查看StandardLiftables ,我无法弄清楚如何解决这个问题。

另一种看待它的方式:

假设我想在编译时使用宏从以下类创建实例:

abstract class ClassWithValidation {
  val predicate: String => Boolean
  def validate(s: String) = predicate(s)
}

我从其他地方检索一个函数文字作为变量值:

val predicate = (s: String) => s.startsWith("Hi")

然后我想简单地将该变量准引用到构造中:

q"""new ClassWithValidation {
      val predicate = $predicate
      // other stuff...
    }"""

但它给了我这个错误:

Error:(46, 28) Can't unquote String => Boolean, consider providing an 
implicit instance of Liftable[String => Boolean]

通常我可以为自定义类型制作这样的隐式 Liftable 。但我还没有找到一种方法对函数文字做同样的事情。有没有办法做到这一点,还是我需要以另一种方式看待它?

4

1 回答 1

3

据我了解,您正试图从一个函数转到表示其源代码的抽象语法树(以便可以将其拼接成宏扩展)。这是人们经常要求的事情(例如,它经常出现在 DSL 中),但是在我们当前的宏系统中没有直接的方法来实现它。

目前您可以做的是在声明函数时显式保存 AST,然后在宏中加载和使用它。最方便的方法是通过另一个宏:https ://gist.github.com/xeno-by/4542402 。人们还可以想象编写一个可以按照相同思路工作的宏注释。

在 Project Palladium 中,有一个计划为每个正在编译的程序保存类型检查树。这意味着很可能会有一个简单的 API,例如treeOf(predicate),它会自动返回包含谓词源的抽象语法树。但这绝对不是一成不变的——我们会看看进展如何,我会在今年的 ScalaDays 上汇报进展情况。

于 2014-04-24T07:24:41.000 回答