Aar*_*rup 18 lisp delegates scala scala-2.8
我最近看到了几个Scala问题(例如这里,这里和这里),它们要求使用代理,并且它在我自己的工作中不止一次出现.Scala库有许多代理特征(14,如果我计算正确的话).
代理类/特征通常包含许多样板:
class FooProxy(val self: Foo) extends Foo {
// added behavior
def mymethod = ...
// forwarding methods
def method1 = self.method1
def method2(arg: String) = self.method2(arg)
...
}
trait Foo {
def method1: Unit
def method2(arg: String): Unit
}
Run Code Online (Sandbox Code Playgroud)
我的第一个想法是定义一个Proxy[T]可以如下使用的特征:
class FooProxy(val self: Foo) extends Proxy[Foo] {
// added behavior
def mymethod = ...
}
Run Code Online (Sandbox Code Playgroud)
哪里trait Proxy[T] extends T.当然,如果Proxy没有编译器魔法,实际上不可能定义特征.
我的下一个想法是寻找一个编译器插件(这种功能显然不在现有的编译器中,或者这14个代理特性的来源会小得多).果然,我找到了Kevin Wright的AutoProxy插件.该插件旨在整齐地解决代理问题,以及其他用例(包括动态混合):
class FooProxy(@proxy val self: Foo) { ... }
Run Code Online (Sandbox Code Playgroud)
不幸的是,它的工作似乎在11月(2009年)停滞不前.所以,我的问题是
Proxy给定lisp风格的宏是不是可以定义特征?四个问题,四个答案
我是,虽然家人必须先来!还有其他人参与了在编译器插件中合成方法的一般问题.
如果是这样,它很可能是以不同的形式,也许不使用注释.
我不知道任何等效的插件,虽然Scala GSOC候选项目之一部分基于我的autoproxy代码.但是,有一个非常干净的解决方案在大多数情况下都可以工作,并且根本不需要编译器插件:您可以定义从FooProxy到Foo的隐式转换,它只返回self成员; 这将使你在那里大部分时间.这种方法的主要问题是,如果你需要使用Java中的代码,它会使生活变得更加困难,它在速度/内存方面可能效率较低,而且你需要注意的是另一个非常明显的问题.
令人沮丧的是,几乎所有必要的逻辑都已在编译器中可用,并且它用于mixins,因此确实应该有一种处理任务的优雅方式.
Adam Warski 最近发表了一篇关于基于宏的方法的博客,该方法可能适用于Scala 2.11,并且肯定适用于Scala 2.10中的Macro Paradise编译器插件.
这个库可以让你写
class FooProxy(@delegate wrapped: Foo) extends Foo {
// added behavior
def mymethod = ...
// forwarding methods (generated for you)
// def method1 = wrapped.method1
// def method2(arg: String) = wrapped.method2(arg)
}
Run Code Online (Sandbox Code Playgroud)
在撰写本文时,该项目处于一个非常早期的概念验证阶段,因此需要谨慎.
| 归档时间: |
|
| 查看次数: |
4013 次 |
| 最近记录: |