Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F#邮箱与邮箱处理器_F#_Ccr - Fatal编程技术网

F#邮箱与邮箱处理器

F#邮箱与邮箱处理器,f#,ccr,F#,Ccr,我注意到邮箱类型是封装的,只能通过使用MailboxProcessor使用 这意味着要有一个可以发布消息的代理,我必须有一个单一类型的邮箱(或者以一种奇特的方式使用现有的MailboxProcessor) 我是否应该理解,为单个工作流使用多个邮箱必然会导致糟糕的设计?Ccr显然给了你这样的自由度 编辑: 正如Daniel指出的,如果一个人想要发送多种类型的消息,DUs优雅地解决了这个问题——而我过去并没有这样做过 但问题是,这样做难道不是一种代码气味吗?随着时间的推移,向代理发送更多类型的消息是

我注意到邮箱类型是封装的,只能通过使用MailboxProcessor使用

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

我是否应该理解,为单个工作流使用多个邮箱必然会导致糟糕的设计?Ccr显然给了你这样的自由度

编辑: 正如Daniel指出的,如果一个人想要发送多种类型的消息,DUs优雅地解决了这个问题——而我过去并没有这样做过


但问题是,这样做难道不是一种代码气味吗?随着时间的推移,向代理发送更多类型的消息是否会导致您承担太多的责任?我有时认为,务必将代理使用的消息类型封装在一个接口后面,这样这些信息就永远不会被公开。

通常,消息类型是一个有区别的联合,它允许在一个邮箱中使用各种消息。这在您的情况下不起作用吗?

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

例如,您可以使用COmega和F#Agent比较一个位置缓冲区的实现:

在本例中,异步方法的行为类似于邮箱(因此有四个邮箱:
empty
contains
Put
Get
),主体的行为类似于处理程序,当邮箱组合包含值时将触发处理程序(即,当您放入空缓冲区或从满缓冲区中取出时)。在F#中,您可以使用
MailboxProcessor
并写入:

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 )

type Message我不认为您能够仅使用一种类型的邮件成功地处理邮箱,除非您从被动扩展中使用类似于
ISubject
类型的邮件。邮件有不同的形式,而且都很重要。我能想到的两个主要示例是:

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

  • 您的想法是正确的,您很可能希望将数据消息限制为某种类型,但从技术上讲,DU是一种有许多替代方案的类型。如果您在L'Agent中采用与Luca相同的初始动态方法,我想他和我都会同意,一个邮箱中的类型太多有点麻烦allenge.

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


    我真的很推荐它,也很乐意听到一些反馈。

    这里绝对不是试图解决问题……这纯粹是设计考虑。我想我没有这么做。我想你是说邮箱被限制为单一邮件类型是有问题的,但DU绕过了这一“限制”同意了,但这并不能说明这种方法的设计质量。但我不清楚,我会更新我的问题。”DavidGrenier:我不熟悉CCR,所以我可能忽略了你的观点。但是我几乎不认为DUS在这个上下文中有代码气味。事实上,我想不出一个更适合这个领域的数据结构。如果你是WRRI。关于一个
    MailboxProcessor
    有太多的职责,你总是可以在幕后委托给专门的处理器。也许我的错误是把基于代理的编程看作是一种开发范例,而不是一种低级的实现细节(比如数组)无论你是否使用代理,这种设计都可以在更高的层次上考虑。我可能被这篇文章误导了:非常有启发性的感谢。显然我必须澄清我的问题:D@Tomas,我注意到您总是使用
    AsyncReplyChannel
    ,即使是在类似
    Put
    这样看似单向的消息上也是如此。这有什么原因吗使用回复防止无序消息?我原以为,
    MailboxProcessor
    只通过
    Post
    @RyanRiley接收消息应该可以正常工作。我不会对一条只调用代理的某些操作的简单消息使用
    AsyncReplyChannel
    。然而,我在这里使用它主要是因为我认为代理的用户可能希望等待,直到代理处理上一条
    Put
    消息。例如,当使用一位缓冲区实现(简单的)生产者/消费者模式时(中间只有一个元素存储)。如果您只想在不等待的情况下向代理发送一些信息,那么使用
    Post
    肯定是可以的。(但是,基于COmega的版本确实不等待
    Put
    ,因此两者是不同的)@Tomas我把我的问题移到了a。谢谢你的回答。也许你可以在那里跟进?你带来的两点不是低级的实现细节吗?1-很明显,2-这必然会导致一个非常粗糙的代理?我当然希望所有这些都能很好地封装在一个接口后面,否则我只是得到了实现细节在我的应用程序中,尾巴到处都是——这在一定程度上证实了我问题中的假设。我发现,使用一种类型的东西往往会让人感到困惑
    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 )