Live data from Hacker News

Zig's new I/O: function coloring is inevitable?

blog.ivnj.org

61–70 of 83 posts

Re: Zig's new I/O: function coloring is inevitable?

#61

Earlier quoted context omitted.

It also has the I/O effect. You don’t need to call or make use of an effect to be “tainted” by it; it just needs to be in the closure (or whatever scope is relevant in the language). Intuitively: if you mark a function as async, it doesn’t stop being async “colored” just because you don’t actually perform any async operations in it. This is the same thing.

you might be talking about stackless coroutines, which are currently not part of zig, in which case, yes, the compiler might [0] have to instantiate different functions under the hood for the stackless-coro and the non-stackless-coro cases, with some mechanism to drop in an executor at the boundaries. until then its really hard to claim that the functions are colored. [0] But even in that case there's not really colo…

No, I really just mean from a PLT perspective. The sync/async implementation used under the hood doesn't matter; what matters is that an `Io` in the closure is a token type for communicating effects. No instantiated or enclosed token; no effects.

People seem to be really defensive about this, like it's a bad thing. It isn't! It's arguably a significantly cleaner way to handle what people confusingly call "coloring." But that doesn't make it not "coloring," because coloring is about effects and vitality, not about keywords and syntax.

Re: Zig's new I/O: function coloring is inevitable?

#62

Earlier quoted context omitted.

you might be talking about stackless coroutines, which are currently not part of zig, in which case, yes, the compiler might [0] have to instantiate different functions under the hood for the stackless-coro and the non-stackless-coro cases, with some mechanism to drop in an executor at the boundaries. until then its really hard to claim that the functions are colored. [0] But even in that case there's not really colo…

No, I really just mean from a PLT perspective. The sync/async implementation used under the hood doesn't matter; what matters is that an `Io` in the closure is a token type for communicating effects. No instantiated or enclosed token; no effects. People seem to be really defensive about this, like it's a bad thing. It isn't! It's arguably a significantly cleaner way to handle what people confusingly call "coloring."…

1. the original author of the function coloring post wad not exactly a theorist so if you're applying some other idea of what coloring is, then you're muddying the waters.

2. here's what i have to say about your idea of what coloring is: That's all fine and good in theory, but in practice it makes no difference, at the user level, or at the compiler level.

Re: Zig's new I/O: function coloring is inevitable?

#63

Earlier quoted context omitted.

No, I really just mean from a PLT perspective. The sync/async implementation used under the hood doesn't matter; what matters is that an `Io` in the closure is a token type for communicating effects. No instantiated or enclosed token; no effects. People seem to be really defensive about this, like it's a bad thing. It isn't! It's arguably a significantly cleaner way to handle what people confusingly call "coloring."…

1. the original author of the function coloring post wad not exactly a theorist so if you're applying some other idea of what coloring is, then you're muddying the waters. 2. here's what i have to say about your idea of what coloring is: That's all fine and good in theory , but in practice it makes no difference, at the user level, or at the compiler level.

I don’t know anything about the original author, but I do know what function coloring is. It’s a way to describe effects. An effect is a function color.

> That's all fine and good in theory, but in practice it makes no difference, at the user level, or at the compiler level

Every example given so far shows Io’s virality, so I don’t know how you can assert how it doesn’t make a difference. The entire point of the design appears (reasonably) to be to introduce a token object that conveys an effect, rather than requiring a runtime to intermediate that effect.

Again, none of this is bad. Effect typing is cool. But it is, by definition, a way to color a function.

(Maybe the confusion here stems from the fact that languages like Go appear to have it “both ways” without coloring. Go is able to do that because it has an intrusive runtime that intermediates asynchronous events. Zig can’t do the same thing without making the same compromises as Go vis a vis FFI performance and ABI compatibility.)

Re: Zig's new I/O: function coloring is inevitable?

#64

Earlier quoted context omitted.

Another 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…

> 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.

> 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.

Re: Zig's new I/O: function coloring is inevitable?

#65

Earlier quoted context omitted.

1. the original author of the function coloring post wad not exactly a theorist so if you're applying some other idea of what coloring is, then you're muddying the waters. 2. here's what i have to say about your idea of what coloring is: That's all fine and good in theory , but in practice it makes no difference, at the user level, or at the compiler level.

I don’t know anything about the original author, but I do know what function coloring is . It’s a way to describe effects. An effect is a function color. > That's all fine and good in theory, but in practice it makes no difference, at the user level, or at the compiler level Every example given so far shows Io’s virality, so I don’t know how you can assert how it doesn’t make a difference. The entire point of the des…

The vtable example is nonviral.

Re: Zig's new I/O: function coloring is inevitable?

#66

Earlier quoted context omitted.

I don’t know anything about the original author, but I do know what function coloring is . It’s a way to describe effects. An effect is a function color. > That's all fine and good in theory, but in practice it makes no difference, at the user level, or at the compiler level Every example given so far shows Io’s virality, so I don’t know how you can assert how it doesn’t make a difference. The entire point of the des…

The vtable example is nonviral.

I don’t see how that can be the case, given that Io is in the closure. Anything that wants to do I/O needs that token; that’s what virality is.

Re: Zig's new I/O: function coloring is inevitable?

#67

Earlier quoted context omitted.

> 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.

Going 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.

Yes, 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.

Re: Zig's new I/O: function coloring is inevitable?

#68

Earlier quoted context omitted.

The vtable example is nonviral.

I don’t see how that can be the case, given that Io is in the closure. Anything that wants to do I/O needs that token; that’s what virality is.

im no virologist but i don't think your definition of viral is reasonable. this is like saying "anything that wants to use a database needs a socket, so a socket is viral"

Re: Zig's new I/O: function coloring is inevitable?

#69
post #11

If you want to go down that route, any function that has, or doesn't have, any given resource is colored then. fn foo(db: *Db) !void { ... } fn bar() !void { ... } Would you consider `foo` a blue function and `bar` a red function? That doesn't seem particularly helpful to me. The virality of async await is that once you mark a function async, then you can only call it from another async function, which forces you to…

> The virality of async await is that once you mark a function async, then you can only call it from another async function Rust calling async function in non-async function: ... // Create the runtime let rt = Runtime::new().unwrap(); // Get a handle from this runtime let handle = rt.handle(); // Execute the future, blocking the current thread until completion handle.block_on(async { println!("hello"); }); https://do…

So that's an escape in Rust and tokio.

But consider a language that doesn't have block_on, like javascript.

Re: Zig's new I/O: function coloring is inevitable?

#70

If you want to go down that route, any function that has, or doesn't have, any given resource is colored then. fn foo(db: *Db) !void { ... } fn bar() !void { ... } Would you consider `foo` a blue function and `bar` a red function? That doesn't seem particularly helpful to me. The virality of async await is that once you mark a function async, then you can only call it from another async function, which forces you to…

> No, because you would just pass that extra argument around and nothing else would have to change. > Semantically, passing std.Io to every function is no different from making every Node.js function async and returning a promise. Zig shifts function coloring from blocking/non-blocking choice to io/non-io. > Complains are about how inconvenient it is to work with [blocking and non-blocking function handling] differen…

They're similar, but if you're not writing Haskell it's super easy to make a variable always be in scope. You don't have to change all the intermediate functions to do it.
Post reply on HN