0

我注意到 Mailbox 类型是封装的,只能通过使用 MailboxProcessor 来使用。

这意味着要拥有一个可以向其发布消息的代理,我不得不拥有一个单一类型的邮箱(或以一种奇特的方式使用现有的 MailboxProcessor)。

我是否应该理解为单个工作流程设置多个邮箱会固有地导致糟糕的设计?Ccr 显然为您提供了那种程度的自由。

编辑:正如丹尼尔所指出的,如果一个人想发送多种消息类型,DUs 可以优雅地解决这个问题——而且我过去并不是没有这样做过。

但问题是,这样做不是代码味道吗?随着时间的推移,向代理添加更多类型的消息不会导致您承担太多责任吗?我有时认为始终将代理使用的消息类型封装在接口后面以使这些信息永远不会暴露是很重要的。

4

4 回答 4

5

我认为 F# 代理使用MailboxProcessor和 CCR 实现了不同的编程模型,但我相信两者都同样强大,尽管肯定有问题可以用一个或另一个更好地解决,所以最好有另一个库F# 围绕邮箱构建。基于 CCR 的编程模型可能在各种基于连接演算的语言中描述得更清楚,例如COmega(这是一个旧的 MSR 项目)。

例如,您可以比较使用 COmega 和 F# 代理的一个地方缓冲区的实现:

public class OnePlaceBuffer {
  private async empty();
  private async contains(string s);

  public OnePlaceBuffer() { empty(); }
  public void Put(string s) & empty() {
    contains(s);
  }
  public string Get() & contains(string s) {
    empty();
    return s;
  }
}

此示例中,异步方法的行为类似于邮箱(因此其中有四个emptycontains和当你从一个完整的缓冲区中获取时)在 F# 中,您可以使用和编写:PutGetMailboxProcessor

type Message<'T> =
  | Put of 'T * AsyncReplyChannel<unit>
  | Get of AsyncReplyChannel<'T>

MailboxProcessor.Start(fun agent ->
  let rec empty = agent.Scan(function
    | Put(v, repl) -> repl.Reply(); Some(full(v))
    | _ -> None)
  and full v = agent.Scan(function
    | Get repl -> repl.Reply(v); Some(empty)
    | _ -> None)
  empty )

这两个实现表达了相同的想法,但方式略有不同。在 F# 中,emptyfull是两个函数,表示代理的不同状态,发送给代理的消息表示代理状态的不同方面(待处理的工作)。在 COmega 实现中,程序的所有状态都由邮箱捕获。

我想将代理的状态与需要处理的即时消息分开可能会更容易考虑 F# MailboxProcessor,但这只是一个直接的想法,没有任何理由......

最后,MailboxProcessor在 F# 中使用的实际应用程序中,您很可能会使用大量它们,并且它们将以某种方式连接起来。例如,实现流水线是使用多个MailboxProcessor实例的应用程序的一个很好的例子(当然,它们都有一些与之关联的简单运行的异步工作流)。有关示例,请参见本文。

于 2011-12-12T23:37:26.470 回答
1

一般来说,消息类型是有区别的联合,它允许在一个邮箱中包含各种类型的消息。这对你的情况不起作用吗?

于 2011-12-12T22:30:06.490 回答
1

我认为您永远无法仅使用一种类型的消息成功地使用邮箱,除非您使用类似ISubjectReactive Extensions 中的类型。消息有不同的形式,而且都很重要。我能想到的两个主要例子是:

  1. 控制消息 - 表示邮箱应该执行的操作,例如清除其队列、查找特定消息、关闭、启动子进程等。
  2. 数据消息 - 发送和接收(Put / Get)是这些的一般类型。

您认为您很可能希望将数据消息限制为某种类型是正确的,但从技术上讲,DU 是一种具有多种选择的类型。如果您要采用与 Luca 在 L'Agent 中最初的动态方法相同的方法,我认为他和我都同意一个邮箱中有太多类型是一个挑战。

于 2011-12-13T16:21:44.757 回答
0

我想我可能已经找到了我要找的东西。我已经听了 Rich Hickey 的演讲(我们到了吗)至少 5 次,我相信他的方法解决了我的许多设计问题。显然,这可以通过 F# 邮箱或 CAS 引用来实现。

我真的推荐它,并很高兴听到一些反馈。

于 2012-06-20T17:55:01.207 回答