【发布时间】:2014-08-28 00:09:53
【问题描述】:
Go 语言有一个select 语句,可用于轮询多个通道并根据哪个通道首先非空来执行特定操作。
例如
select {
case a := <- chanA:
foo(a)
case b := <- chanB:
baz(b)
case c := <- chanC:
bar(c)
}
这将等到chanA、chanB 或chanC 非空,然后如果chanB 非空,它将从chanB 读取并将结果存储在@987654329 @,然后拨打baz(b)。还可以添加default: 子句,这意味着select 语句不会在通道上等待,而是会在所有通道为空时执行default 子句的任何操作。
在 Haskell 中为 STM TChans 实现这样的最佳方法是什么?它可以通过 if-else 链简单地完成:检查每个 chan isEmptyChan,如果它不为空,则从中读取并调用适当的函数,或者如果所有通道都是空的,则调用 retry。我想知道是否会有更优雅/惯用的方式来做到这一点?
请注意,Go 的 select 语句也可以在其 case 中包含 send 语句,并且只有在其通道为空时才会完成一个 send 语句。如果该功能也可以复制,那就太好了,尽管我不确定是否会有一种优雅的方式来做到这一点。
只是稍微相关,但我刚刚注意到了一些内容,但我不确定在哪里发布:retry 描述中的 Control.Monad.STM 页面上有一个错字:
“实现可能会阻塞线程,直到它已读取的 TVar 之一被更新。”
【问题讨论】:
-
你可能想从
Control.Concurrent.Async看race。 -
值得注意的是,go 不会执行第一个可用的操作,而是随机选择的任何可用的操作。它特别不会仅仅因为它们是稍后定义的或在选择路径中不走运而使频道饿死。
-
这与 Go 的
select完全不同。 Go 中的通道是有界的,不像TChan(使它们真正有用),select可以与发送操作一起使用。
标签: haskell select channel stm