Live data from Hacker News

Zig's New Async I/O

kristoff.it

41–50 of 293 posts

Re: Zig's New Async I/O

#41
post #15

Seeing a systems language like Zig require runtime polymorphism for something as common as standard IO operations seems off to me -- why force that runtime overhead on everyone when the concrete IO implementation could be known statically in almost all practical cases?

I/O strikes me as one place where dynamic dispatch overhead would likely be negligible in practice. Obviously it depends on the I/O target and would need to be measured, but they don't call them "I/O bound" (as opposed to "CPU bound") programs for no reason.

Re: Zig's New Async I/O

#42
post #3

I feel that I have to point this out once again, because the article goes so far as to state that: > With this last improvement Zig has completely defeated function coloring. I disagree with this. Let's look at the 5 rules referenced in the famous "What color is your function?" article referenced here. > 1. Every function has a color Well, you don't have async/sync/red/blue anymore, but you now have IO and non-IO fun…

> Well, you don't have async/sync/red/blue anymore, but you now have IO and non-IO functions.

> However, the coloring problem hasn't really been defeated.

Well, yes, but if the only way to do I/O were to have an Io instance to do it with then Io would infect all but pure(ish, non-Io) functions, so calling Io functions would be possible in all but those contexts where calling Io functions is explicitly something you don't want to be possible.

So in a way the color problem is lessened.

And on top of that you get something like Haskell's IO monad (ok, no monad, but an IO interface). Not too shabby, though you're right of course.

Next Zig will want monadic interfaces so that functions only have to have one special argument that can then be hidden.

Re: Zig's New Async I/O

#43

Earlier quoted context omitted.

> (And before anyone mentions it, devirtualization is a myth, sorry) In Zig it's going to be a language feature, thanks to its single unit compilation model. https://github.com/ziglang/zig/issues/23367

Wouldn't this only work if there's only one implementation throughout the entire compliation unit? If you use 2 allocators in your app, your restricted function type has 2 possible callees for each entry, and you're back to the same problem.

> A side effect of proposal #23367, which is needed for determining upper bound stack size, is guaranteed de-virtualization when there is only one Io implementation being used (also in debug builds!).

> In the less common case when a program instantiates more than one Io implementation, virtual calls done through the Io interface will not be de-virtualized, as that would imply doubling the amount of machine code generated, creating massive code bloat.

From the article

Re: Zig's New Async I/O

#44
post #36
post #14

Earlier quoted context omitted.

Go also suffers from this form of “subtle coloring”. If you’re working with goroutines, you would always pass in a context parameter to handle cancellation. Many library functions also require context, which poisons the rest of your functions. Technically, you don’t have to use context for a goroutine and could stub every dependency with context.Background, but that’s very discouraged.

Context is not required in Go and I personally encourage you to avoid it. There is no shame in blazing a different path.

Why do you encourage avoiding it? Afaik it's the only way to early-abort an operation since Goroutines operate in a cooperative, not preemptive, paradigm. To be very clear, I'm asking this completely in good faith looking to learn something new!

Re: Zig's New Async I/O

#45
post #3

I feel that I have to point this out once again, because the article goes so far as to state that: > With this last improvement Zig has completely defeated function coloring. I disagree with this. Let's look at the 5 rules referenced in the famous "What color is your function?" article referenced here. > 1. Every function has a color Well, you don't have async/sync/red/blue anymore, but you now have IO and non-IO fun…

The original “function colouring” blogpost has done irreparable damage to PL discussions because it’s such a stupid concept to begin with. Of course I want async functions to be “coloured” differently, they do different things! How else is a “normal function” supposed to call a function that gives you a result later——obviously you want to be forced to say what to do with the result; await it, ignore it, .then() in JS terms, etc. these are important decisions that you can’t just ignore because it’s “painful”

Re: Zig's New Async I/O

#46
post #19
post #12

Earlier quoted context omitted.

Aside from the ridiculous argument that function parameters color them, the assertion that you can’t call a function that takes IO from inside a function that does not is false, since you can initialize one to pass it in

To me, there's no difference between the IO param and async/await. Adding either one causes it to not be callable from certain places. As for the second thing: You can do that, but... You can also do this in Rust. Yet nobody would say Rust has solved function coloring. Also, check this part of the article: > In the less common case when a program instantiates more than one Io implementation, virtual calls done throug…

>To me, there's no difference between the IO param and async/await.

You can't pass around "async/await" as a value attached to another object. You can do that with the IO param. That is very different.

Re: Zig's New Async I/O

#47
post #8
post #3

I feel that I have to point this out once again, because the article goes so far as to state that: > With this last improvement Zig has completely defeated function coloring. I disagree with this. Let's look at the 5 rules referenced in the famous "What color is your function?" article referenced here. > 1. Every function has a color Well, you don't have async/sync/red/blue anymore, but you now have IO and non-IO fun…

The key difference to typical async function coloring is that `Io` isn't something you need specifically for asynchronicity; it's something which (unless you make a point to reach into very low-level primitives) you will need in order to perform any IO, including reading a file, sleeping, getting the time, etc. It's also just a value which you can keep wherever you want, rather than a special attribute/property of a…

> It's quite rare for a function to unexpectedly gain a dependency on "doing IO" in general.

From the code sample it looks like printing to stdio will now require an Io param. So won’t you now have to pass that down to wherever you want to do a quick debug printf?

Re: Zig's New Async I/O

#48
post #36

Earlier quoted context omitted.

Context is not required in Go and I personally encourage you to avoid it. There is no shame in blazing a different path.

Why do you encourage avoiding it? Afaik it's the only way to early-abort an operation since Goroutines operate in a cooperative, not preemptive, paradigm. To be very clear, I'm asking this completely in good faith looking to learn something new!

You are expecting them to actually check the value, there is nothing preemptive.

Another approach is special messages over a side channel.

Re: Zig's New Async I/O

#49
post #26

I don't know Zig, but wouldn't such a change be a major breaking change where all prior Zig code doing Io wouldn't work anymore if upgraded?

Breaking changes is just another Tuesday for Zig.

Re: Zig's New Async I/O

#50
post #47
post #8

Earlier quoted context omitted.

The key difference to typical async function coloring is that `Io` isn't something you need specifically for asynchronicity; it's something which (unless you make a point to reach into very low-level primitives) you will need in order to perform any IO, including reading a file, sleeping, getting the time, etc. It's also just a value which you can keep wherever you want, rather than a special attribute/property of a…

> It's quite rare for a function to unexpectedly gain a dependency on "doing IO" in general. From the code sample it looks like printing to stdio will now require an Io param. So won’t you now have to pass that down to wherever you want to do a quick debug printf?

I'm not familiar with Zig, but won't the classic "blocking" APIs still be around? I'd rather a synchronous debug print either way.
Post reply on HN