实现该协议需要两个双向通道似乎很奇怪。难道我们不能只使用一个通道并更改服务器循环以提供和接收该单个通道。请注意,这在 Hopac 中是允许的并且没有问题。作业不能在单个同步操作中使用通道向自己发送消息。解释如果只有一个通道而不是单独的 getCh 和 putCh 通道会出现什么问题。提示:考虑有多个客户的情况。
以上来自Hopac 文档。
新用户是否真的希望在旅程的这一点上了解图书馆实施的细节?当文档给出答案而不是提出问题时,我更喜欢它。为什么同时使用单个通道take
并且get
是一个坏主意的原因是什么?
module HopacExample
open System
open Hopac
open Hopac.Infixes
type Cell<'a> = {
takeCh : Ch<'a>
putCh : Ch<'a>
}
let get c = Ch.take c.takeCh
let put c (x: 'a) = Ch.give c.putCh x
let cell x = Job.delay <| fun () ->
let c = {takeCh = Ch (); putCh = Ch ()}
let server x =
Alt.choose [
Ch.take c.putCh
Ch.give c.takeCh x ^->. x]
Job.iterateServer x server >>-. c
run <| job {
let! c = cell 1
let print () = Job.start (get c >>- fun i -> printf "%i\n" i)
let put i = Job.start (put c i)
do! print()
do! put 2
do! print()
do! put 3
do! print()
do! put 4
do! print()
do! put 5
do! print()
do! put 6
do! print()
}
Console.ReadKey()
2
3
4
4
5
6
module HopacExample2
open System
open Hopac
open Hopac.Infixes
let get c = Ch.take c
let put c (x: 'a) = Ch.give c x
let cell x = Job.delay <| fun () ->
let c = Ch ()
let server x =
Alt.choose [
Ch.take c
Ch.give c x ^->. x]
Job.iterateServer x server >>-. c
run <| job {
let! c = cell 1
let print () = Job.start (get c >>- fun i -> printf "%i\n" i)
let put i = Job.start (put c i)
do! print()
do! put 2
do! print()
do! put 3
do! print()
do! put 4
do! print()
do! put 5
do! print()
do! put 6
do! print()
}
Console.ReadKey()
5
5
5
5
5
6
有一些差异,但没有什么我不会归因于并发的变幻莫测。