11 ms·
I've been trying to beat this point in and failing. If a parameter type creates "colors", you can extrapolate that to an infinite set of colors in every single
by n42 1y ago
I've been trying to beat this point in and failing. If a parameter type creates "colors", you can extrapolate that to an infinite set of colors in every single language and every single standard library, and the discussion on colors becomes meaningless.
Some people are so focused on categorical thinking that they are missing the forest for the trees.
The colors are a means of describing an observed outcome -- in Node's case, callback hell, in Rust's, 4 different standard libraries. Whatever it may be, the point is not that there are colors, it's the impact on there being colors.
> But there is a catch: with this new I/O approach it is impossible to write to a file without std.Io!
This sentence just makes me laugh, like it's some kind of "gotcha". It is the ENTIRE BASIS of the design!
- deleted 1y ago[deleted]
- dwattttt 1y ago> you can extrapolate that to an infinite set of colors in every single language and every single standard library, and the discussion on colors becomes meaningless. It's more that discussion about most of them becomes meaningless, because they're trivial. We only care when it's hard to swap between "colours", so e.g. making it easy to call an Io function from a non-Io function "removes" the colouring problem.
- hamandcheese 1y ago> so e.g. making it easy to call an Io function from a non-Io function "removes" the colouring problem. Exactly. In golang (which is also a cooperatively multithreaded runtime if I understand correctly), calling a function that needs IO does not infect the callers type signature. In async rust, and in "async param" zig, it does.
- naasking 1y agoAnother poster up thread identified the exact problem: async/await contexts are not first-class values, they are second class citizens. If they were values then you could just stick the context in a struct/class and pass that around instead, and avoid having to refactor call chains every time something changes. It's their second class status that forces the "colouring" into the function signature itself at each point. This is also why ordinary first class values do not introduce colours, ie. you can hide new values/parameters inside other types that are already part of the function signature, thus halting the propagation/vitality of the change. Of course, if these async contexts were first class citizens then you've basically just reinvented delimited continuations, and that introduces complications that compiler writers want to avoid, which is why async/await are second citizens.
- SkiFire13 1y ago> async/await contexts are not first-class values Because async/await are not values, they are ways to run/structure your code. That's why they are so infectious. If you don't want the division the only solution is to make everything of one kind. Languages like C make everything sync/blocking, while languages like Go make everything async.
- dwattttt 1y ago> the only solution is to make everything of one kind That's not really the case. All you really need is a way to run async code from a sync function; "keep doing this async thing until it's done" is the primitive you need, and some languages/runtimes offer this.
- SkiFire13 1y agoGoing by that reasoning then Rust solved the colored function problem too: when calling an `async` function from a sync one use `block_on`, while when calling a sync blocking function from an `async` one use `spawn_blocking`, but somehow people are not happy with this.
- dwattttt 1y agoYes, it's quite curious. Having used both block_on and spawn_blocking, and not being worried about what "colour" my function is, I am also quite confused about the fuss. On a practical note, since Rust doesn't standardise on an async runtime, it would be more accurate to say tokio solved the coloured function problem, for whatever that means. Or any and everyone else that made it easy to call one coloured function from another.
- naasking 1y ago> Because async/await are not values They are computations that produce values. Computations can be reified as values. What do you think functions and threads are? As I described above, "delimited continuations" are values that subsume async/await and many other kinds of effects. You can handle async/await like any other value if they were reified as delimited continuations, but this makes the compiler writer's life much more difficult.
- vips7L 1y agoGo is preemptive. Async/await is cooperative because you’re explicitly cooperating and yield.