有没有办法为功能性文字制作Liftable(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。但是我还没有找到一种方法来为功能性文字做同样的事情。有没有办法做到这一点,还是我需要以另一种方式看待它?
答案 0 :(得分:3)
根据我的理解,你试图从一个函数转到一个代表其源代码的抽象语法树(这样它就可以拼接成一个宏扩展)。这是人们要求的常见事情(例如,它经常出现在DSL中),但在我们当前的宏系统中没有直接的方法来实现这一点。
目前您可以做的是在声明函数时明确保存AST,然后在宏中加载并使用它。最方便的方法是通过另一个宏:https://gist.github.com/xeno-by/4542402。人们还可以想象编写一个可以沿着相同的路线工作的宏注释。
在Project Palladium中,有计划为每个正在编译的程序保存类型树。这意味着很可能是一个简单的API,例如treeOf(predicate)
将自动返回包含谓词源的抽象语法树。但这绝对不是一成不变的 - 我们会看到它如何发展,我将在今年的ScalaDays上报告进展情况。