我已经获得了一个java api,用于通过基于回调的样式连接和通过专用总线进行通信。我目前正在scala中实现一个概念验证应用程序,我正在尝试研究如何生成一个稍微更惯用的scala接口。
典型的(简化的)应用程序可能在Java中看起来像这样:
DataType type = new DataType();
BusConnector con = new BusConnector();
con.waitForData(type.getClass()).addListener(new IListener<DataType>() {
public void onEvent(DataType t) {
//some stuff happens in here, and then we need some more data
con.waitForData(anotherType.getClass()).addListener(new IListener<anotherType>() {
public void onEvent(anotherType t) {
//we do more stuff in here, and so on
}
});
}
});
//now we've got the behaviours set up we call
con.start();
在scala中,我可以明确地定义从(T =&gt; Unit)到IListener的隐式转换,这肯定会让事情变得更简单:
implicit def func2Ilistener[T](f: (T => Unit)) : IListener[T] = new IListener[T]{
def onEvent(t:T) = f
}
val con = new BusConnector
con.waitForData(DataType.getClass).addListener( (d:DataType) => {
//some stuff, then another wait for stuff
con.waitForData(OtherType.getClass).addListener( (o:OtherType) => {
//etc
})
})
这看起来让我想起了scalaz promises和f#async工作流程。
我的问题是:
我可以将其转换为for comprehension或类似的惯用语(我觉得这应该合理地映射到演员)
理想情况下,我希望看到类似的内容:
for(
d <- con.waitForData(DataType.getClass);
val _ = doSomethingWith(d);
o <- con.waitForData(OtherType.getClass)
//etc
)
答案 0 :(得分:6)
如果您想对此使用for
理解,我建议您查看Scala语言规范,了解如何将理解扩展为map
,flatMap
等。将为您提供有关此结构如何与您已经获得的内容相关的一些线索(嵌套调用addListener
)。然后,您可以将waitForData
调用的返回类型的隐式转换添加到具有委派给map
的相应flatMap
,addListener
等方法的新类型。< / p>
<强>更新强>
我认为您可以使用标准库中的scala.Responder[T]
:
假设addListener
的班级名为Dispatcher[T]
:
trait Dispatcher[T] {
def addListener(listener: IListener[T]): Unit
}
trait IListener[T] {
def onEvent(t: T): Unit
}
implicit def dispatcher2Responder[T](d: Dispatcher[T]):Responder[T] = new Responder[T} {
def respond(k: T => Unit) = d.addListener(new IListener[T] {
def onEvent(t:T) = k
})
}
然后您可以按要求使用此
for(
d <- con.waitForData(DataType.getClass);
val _ = doSomethingWith(d);
o <- con.waitForData(OtherType.getClass)
//etc
) ()
使用Responder[T]
查看Comet聊天应用程序时,请参阅the Scala wiki和this presentation。
答案 1 :(得分:3)
我的Scala经验非常少,但如果我实现这样的东西,我会利用actor机制而不是使用回调监听器类。演员是为异步通信而制作的,他们很好地为您分离了应用程序的不同部分。您也可以让他们向多个听众发送消息。
我们必须等待一个“真正的”Scala程序员来充实这个想法。 ;)