In my current job, I mostly write (non-async) python, and I find it to be a performance footgun that you cannot trivially tell when a method call will trigger I/O, which makes it incredibly easy for our devs to end up with N+1-style queries without realizing it.
With async/await, devs are always forced into awareness of where these operations do and don’t occur, and are much more likely to manage them effectively.
FWIW: The zig approach also seems great here, as the explicit Io function argument seems likely to force a similar acknowledgement from the developer. And without introducing new syntax at that! Am excited to see how well it works in practice.
1) It tracks code property which is usually omitted in sync code (i.e. most languages do not mark functions with "does IO"). Why IO is more important than "may panic", "uses bounded stack", "may perform allocations", etc.?
2) It implements an ad-hoc problem-specific effect system with various warts. And working around those warts requires re-implementation of half of the language.
Rust could use these markers as well.
I felt like a `panic` label for functions would be nice, but if we start stacking labels it becomes cumbersome:
pub async panic alloc fn foo() {}
That feels dense.I think ideally it would be something readers could spot at first glance, not something inferred.
No, it's not. `async` is just syntax sugar, the "effect" gets emulated in the type system using `Future`. This is one of the reasons why the `async` system feels so foreign and requires so many language changes to make it remotely usable. `const` is much closer to a "true" effect (well, to be precise it's an anti-effect, but it's not important right now).
Also, I think it's useful to distinguish between effect and type systems, instead of lumping them into just "type system". The former applies to code and the latter to data.
>That feels dense.
Yes. But why `async` is more important than `alloc`? For some applications it's as important to know about potential allocations, as for other applications to know about whether code potentially yields or not.
Explicitly listing all effects would the most straightforward approach, but I think a more practical approach would be to have a list of "default effects", which can be overwritten on the crate (or maybe even module) level. And on the function level you will be able to opt-in or opt-out from effects if needed.
>I think ideally it would be something readers could spot at first glance
Well, you either can have "dense" or explicit "at first glance" signatures.