On Tue, Apr 4, 2023 at 2:22 AM Nigel Tao <nigel...@golang.org> wrote:
> > I'd have to study mux9p for longer, but its select chooses between two > receives, so it could possibly collapse to a single heterogenous > channel. Indeed, both its channels are already heterogenous in some > sense. Both its processTx and processRx methods say "switch > m.tx.Type". > > If you crank that idea to the max, you can get away with a single mailbox for a goroutine, much like in the sense Erlang is doing it. This approach, however, sacrifices type information which is currently being upheld by the ability to select on multiple channels, each of which have different types. In my experience, the concurrency primitives are malleable in many programming languages, and you can implement one model with another, albeit at a heavy efficiency penalty due to translation. I wouldn't be surprised if you find that a simpler model will work in 95% of all cases, and that you can find workarounds for the remaining 5% to the point where you are going to ask "what's the point?" I think the answer is "elegance and simplicity". A view: a select statement is a synchronization of an event. A channel read or a channel write is an event. The select statement is an algebraic concat operation, in the sense it takes an array of such events and produces a new event. We often think of these events as being either "we receive something" or "we send something". But select-statements also allow for their combination of "we either send or receive something". Sometimes, serializing those events into a "send, then receive" or "receive, then send" pattern is fairly easy. Sometimes, it is exceedingly hard to pull off, and the parallel send/recv pattern is just that much more elegant and clearer. The key problem is that sends and/or receives can block, thus obstructing the other event from being processed. You can alleviate this by tasting each channel through a poll. But those solutions often end up being convoluted. To hammer it in even more: a select statement is more than just a single concat. It also contains a body for each event. That body allows you to mediate between different event types, so even if the type of the channel varies, the rest of the code doesn't have to deal with the variance. If you want a model which works locally, non-distributed, and cranks the above ideas even more, you should look at Concurrent ML. In that language, events are first-class values which can be manipulated by programs. There's no select, but you have lower level primitives which allows you to construct one when you need it. The key difference to something like Go is that you can dynamically build up a select as you go and then synchronize it. In Go, such statements are static in the program, and you have to resort to tricks where you disable channels by setting their variables to nil. The perhaps most interesting part of CML is the `withNACK` construction. It allows you to carry out an action if *another* event ends up being chosen. If you squint your eyes---it has to be really really hard, admittedly---it's a vast generalization of Go's `defer`. Where defer cleans up on aborts in functions, withNACK cleans up after aborted events (under a select). -- J. -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAGrdgiVCcGLXbZEOOfs%3DXn_6xS4MUddTxkmfkWe8e3k4sqtSdw%40mail.gmail.com.