9

我已经获得了一个 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 => 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(
  d <- con.waitForData(DataType.getClass);
  val _ = doSomethingWith(d);
  o <- con.waitForData(OtherType.getClass)
  //etc
)
4

2 回答 2

6

如果您想for对此使用推导,我建议您查看 Scala 语言规范,了解如何将 for 推导扩展为map,flatMap等。这将为您提供一些关于此结构与您已经拥有的结构的关系的线索(嵌套调用addListener)。然后,您可以waitForData使用委托给.mapflatMapaddListener

更新

我认为您可以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
) ()

请参阅Scala wiki和有关使用Comet 聊天应用程序的演示文稿。Responder[T]

于 2010-04-24T19:35:46.743 回答
3

我几乎没有 Scala 经验,但如果我要实现这样的东西,我会寻求利用演员机制而不是使用回调侦听器类。Actors 是为异步通信而设计的,它们很好地为您分离了应用程序的不同部分。您还可以让他们向多个侦听器发送消息。

不过,我们将不得不等待一个“真正的”Scala 程序员来充实这个想法。;)

于 2010-04-24T16:18:21.327 回答