Zig的新I/O:功能着色是不可避免的吗?
Zig's new I/O: function coloring is inevitable?

原始链接: https://blog.ivnj.org/post/function-coloring-is-inevitable

博客文章分析了Zig的新I/O系统,认为它并不能真正解决Bob Nystrom突出显示的“功能着色”问题。尽管Zig的目标是统一的语法,但作者认为它仅将着色从阻塞/非阻滞转移到I/O/NON-I/O,因为必须将``std.io''转移到I/O操作。 这与Node.js的显式`async'和``Promise''构造进行了比较。 作者认为,函数是否需要I/O成为类似于功能着色的语义区别,因为您不能没有std.io'执行I/O。他们列出了Zig方法无法消除着色的几个原因。 最终,作者认为,真正消除功能着色是不可能的,因为始终存在I/O敏感功能。 但是,他们赞扬了Zig的I/O设计,用于通过统一封锁和非阻滞操作来改善人体工程学。他们承认到处传递“ std.io”的烦恼,但有益地将其与`s std.mem.solocator'相提并论,突出了其对呼叫者的清晰度和灵活性。

该黑客新闻讨论围绕着Zig的新I/O方法,以及它是否避免了“功能着色”问题,例如JavaScript和``async/ategait''等语言中普遍存在。 功能着色是指“异步”的病毒性质,其中单个异步函数迫使其呼叫者也变得异步,从而导致代码重复和复杂性。 Zig的方法使用明确的参数传递,其中需要I/O的功能必须接收`io'接口。 辩论集中在传递此“ IO”参数是否只是函数着色的另一种形式,因为它仍然需要更改呼叫堆栈。有人认为这是一种问题较小的形式,因为它更明确,并且允许同步和异步代码更容易互操作。 反对这是“着色”的关键参数强调,没有`io'参数的功能仍然可以通过获取或创建``io'实例来调用它来使用它来使用它。 辩论还涉及传递其他参数(例如分配器)是否还构成“着色”,以及焦点是否应该放在区分的 *影响 *上,而不是仅仅存在不同函数签名。总体而言,新方法对其明确的性质和减轻与异步/等待相关的疼痛点的潜力获得了积极的接受。
相关文章

原文

Background

Blog post What Color is Your Function? (2015) by Bob Nystrom highlighted problems of async computation handling in programming language design. It has started heated discussions on Hacker News and Reddit.

Although many solutions to this problem were suggested, none of them seemed to be a silver bullet.

Zig’s new I/O

In the Zig Roadmap 2026 stream Andrew Kelley announced a new way of doing I/O, and Loris Cro wrote a Zig’s New Async I/O blog post describing it in more details.

This is the example Zig code from that post, that writes data to two files asynchronously:

Does this mean that the programming language needs to treat them in the same way?

Ergonomics

But most complains related to function coloring are not that blocking and non-blocking functions need to be handled differently. Complains are about how inconvenient it is to work with these differences. Understanding this moves the problem from computer science to the programming language design - how to make it more convenient?

And this is where I think Zig’s new I/O design does a great job. It unifies the way of working with both execution models elegantly. Although passing std.Io everywhere seems to be annoying, it seems to work well for passing std.mem.Allocator to any function that allocates. It keeps intent clear and gives great flexibility to the caller.

And as with allocation, not every bit of behavior needs to be expressed in the type signature: function does not tell who owns allocated memory, developer either needs to read the docs or go through the code to find out for themselves.

Further reading

联系我们 contact @ memedata.com