3 ms·
What I like about this post is that it provides a good attack against the function coloring philosophy, which always rubbed me the wrong way. Function coloring
by jcranmer 3y ago
What I like about this post is that it provides a good attack against the function coloring philosophy, which always rubbed me the wrong way. Function coloring essentially implies that there's no good reason for async and sync to be different, and it's being used as an argument that we should try to sweep the distinction between the two under the rug as much as possible, and that's just not a good idea.
I also like the point that maybe(async) isn't terribly compelling. Recently, I've been looking at building an async parser, and the sync version of the interface is pretty simple: fn parse(r: &mut dyn Read) -> Result<ParsedObj> [1]. In theory, I could slap an async on it, change Read to AsyncRead, and now I have an async version. Except it's not usefully async: the consumer of the data can't do anything until everything has been fully read in. So what you want in the asynchronous version of the API is something that looks like a stream of parse events. But that API is way too much faff for anyone trying to use the API synchronously. Or is it? If you have a high-level method that distilled the stream of output events into a simple, easy-to-use answer, then you end up with something that looks maybe(async)-able [2].
Where I think the author gets it wrong, though, is in asserting that it's statefulness that causes maybe(async) to break down. State per se isn't the problem: our underlying parser above is statefully turning a stream of input data into a stream of parse events, and this could sometimes work well with maybe(async). The problem arises when you're multiplexing many streams at once. In synchronous code, there's just no way to do that kind of multiplexing (as pointed out earlier in the blog post), while it's a pretty key design feature of async code. The trouble really comes in when you have a system whose outer interface is a 1:1 stream interface, but which internally needs to go through a 1:N piece and an N:1 piece. It looks like it could be maybe(async)-able from the outside, but its implementation is hopelessly not maybe(async)-able.
[1] Honestly, a lot of parsers go a step further and just read in the input buffer as a &[u8] and rely on zero-copy, but that interface turns out to be even less useful in an async context.
[2] But the faff remains if you can't resort to one of the pre-canned methods. How much of an issue that ends up being is left to the reader to decide.
- withoutboats3 3y agoYou’re right, state isn’t really what I meant. I meant exactly the sort of concurrent collating you allude to.