12 ms·
I'm too dumb for Zig's new IO interface
- stop50 1y agoI have never understood libraries or imterfaces that want me to allocate buffers for their type. I can't parse them (no need for the lib then) or write to them (would probably break the exchange). The weird interface of go is probably due the fact that some interfaces can be used to extemd the writer like the hijacker interface (ResponseWriter.(http.Hijacker)) and the request object is used multiple times with different middlewares interacting with it. In short: request does not need to be extended, but the response can be an websocket, an wrapped tcp connection or something else.
- benreesman 1y agoIt's just a different convention like radians and degrees. You can lift/unlift in or out of arbitrary IO, in some languages one direction is called a mock, in other languages the opposite is called unsafeFoo. Andrew Kelley independently rediscovered on a live stream 30 years of the best minds in Haskell writing papers. So the future is Zig. He got there first.
- pjmlp 1y agoOnly if use after free story actually gets fixed, and not by repurposing what has already existed in the C and C++ ecosystems for the last 30 years, like PurifyPlus or VC++ debug allocator.
- benreesman 1y agoIf you mean running clang-tidy as a separate build step or ASAN in a different category than other soundness checks? Compute is getting tight, lots of trends, the age of C++ is winding down gracefully. The age of Zig is emerging delibetately, and the stuff in the middle will end up in the same historical trash bin as everything else in the Altman Era: the misfortunes of losing sight of the technology.
- pjmlp 1y agoI mean those and other ones, we already have enough unsafe languages as it is. The age of C++ is going great, despite all its warts and unsafety, thanks to compiler frameworks like GCC and LLVM, games industry, GPGPU and Khronos APIs. Even if C++ loses everywhere else, it has enough industry mindshare to keep being relevant. Same applies to C, in the context of UNIX clones, POSIX, Khronos, embedded. Being like Modula-2 or Object Pascal in safety, in C like syntax, isn't enough.
- benreesman 1y agoHaskell makes guarantees. Modern C++ makes predictions to within a quantifiable epsilon. Rust makes false promises in practical situations. It invented a notion of safety that is neither well posed, nor particularly useful, nor compatible with ergonomic and efficient computing. It's speciality is marketing and we already know the bounding box on its impact or relevance. "Vibe coding" will be a more colorful and better remembered mile marker of this lousy decade in computers than Rust, which will be an obscurity in an appendix in 100 years.
- simonask 1y agoThere is almost nothing accurate about this comment. "Makes predictions to within a quantifiable epsilon"? What in the world do you mean? The industry experience with C++ is that it is extremely difficult (i.e., expensive) to get right, and C++20 or newer does not change anything about that. Whatever "epsilon" you are talking about here surely has to be very large for a number bearing that sobriquet. As for the mindless anti-Rust slander... I'm not sure it's worth addressing, because it reflects a complete lack of the faintest idea about what it actually does, or what problem it solves. Let me just say there's a reason the Rust community is rife with highly competent C++ refugees.
- Ygg2 1y agoTo be fair to GP, an error bar of 3±300 is still a quantifiable epsilon. Utterly useless, but quantifiable.
- deleted 1y ago[deleted]
- kllrnohj 1y ago> So the future is Zig. He got there first. The future is many things, but a love letter to C is definitely not it. Zig is cute and a fun hobby project that might see above average success for a hobby project. But that's about it. It doesn't address the problems people actually have with C++, not like Rust or Swift do, and it certainly isn't going to attract any attention from the Java, JavaScript, C#, Python, etc... of the world.
- davemp 1y agoZig is not a hobby project. > It doesn't address the problems people actually have with C++, not like Rust or Swift do Speak for yourself. Zig addresses pretty much all of my problems with C++: - terrible compile times - overly complex and still underpowered template/meta programming - fragmented/ancient build tools - actually good enums/tagged unions - exceptions - outdated OOP baggage I don’t actually mind C++ that much, but Zig checks pretty much all of my boxes. Rust/swift check some of these but not all and add a few of their own. > and it certainly isn't going to attract any attention from the Java, JavaScript, C#, Python, etc... of the world. Yeah of course. Zig isn’t trying to be a max ergonomics scripting language…
- geon 1y agoIsn’t the whole point of an external buffer that the function won’t need to allocate?
- deleted 1y ago[deleted]
- kelnos 1y ago> I have never understood libraries or imterfaces that want me to allocate buffers for their type. That doesn't seem that odd to me. It's a trade off: more flexibility, but more manual work. Maybe I have a buffer that I've allocated that I'm not using anymore (say I have a buffer pool) and want to use it again. If the type allocates its own behind the scenes, I can't do that. Or maybe I'm working in an environment where I need to statically allocate all of my resources up-front, and can't allocate later. The big downside is that if 90% of people are just going to allocate a buffer and pass it in, it sucks that 90% of people need to do more work and understand more minutiae when only 10% of the people actually need to. The holy grail is to give lots of flexibility, but make the simple/common case easy. A simple improvement to this interface might be to allow the caller to pass a zero-length buffer (or Zig's version of null), and then the type will allocate its own buffer. Of course, there's still a documentation burden so people know they can do that. Another option could be to have second constructor function that takes no buffer arguments at all, which allocates the buffers and passes them to the fully-flexible constructor function.
- jeroenhd 1y ago> If the type allocates its own behind the scenes, I can't do that. Isn't that the reason why Zig passes around allocators everywhere? If you're using a buffer pool, you should probably be handing out some kind of buffer pool allocator. Requiring all allocation to have happened before execution is still a good reason to pass buffers around, but I feel like the other situations you describe can be solved by just passing the right allocators.
- deleted 1y ago[deleted]
- Galanwe 1y agoThe Zig's language is really good, but the standard library is really a big work in progress, constantly shifting, missing a lot of bits, overly abstracted at some places and too low level at other places. I would say just stay away from the standard library for now and use your OS API, unless you're willing to be a beta tester.
- omgtehlion 1y agoYup, exactly how I use zig most of the time: just use good old OS apis, it is very easy to use cImports, when I'm too lazy to create zig definitions )
- norir 1y agoFrom my perspective, Zig is trying to do far too many things to ever reach a baseline of goodness that I consider acceptable. They are in my view quite disrespectful to their users who they force to endure churn at the whims of their dictator. Now that enough people have bought in and accepted that a broken tool is ok so long as it hasn't been blessed with a 1.0 all of its clear flaws can be overlooked in the hope of the coming utopia (spoiler alert: that day will never arrive). Personally, I think it is wrong to inflict your experiments on other people and when you pull the rug out from underneath say, well, we told you it was unstable, you should't have depended on us in the first place. I don't even understand what zig is supposed to be. Matklad seems to think it is a machine level language: https://lobste.rs/s/ntruuu/lobsters_interview_with_matklad https://lobste.rs/s/ntruuu/lobsters_interview_with_matklad. This contrasts with the official language landing page: Zig is a general-purpose programming language and toolchain for maintaining robust, optimal and reusable software. These two definitions are mutually incompatible. Moreover, zig is clearly not a general purpose language because there are plenty of programming problems where manual memory management is neither needed nor desirable. All of this confusion is manifest in zig's instability and bloated standard library. Indeed a huge standard library is incompatible with the claims of simplicity and generality they frequently make. Async is not a feature that can be implemented universally without adding overhead and indirection because of the fundamental differences in capabilities exposed by the various platforms. Again, they are promising a silver bullet even though their prior attempt, in which they publicly proclaimed function coloring to be solved, has been abandoned. Why would we trust them to get it right a second time? There are a very small number of assembly primitives that every platform provides that are necessary to implement a compiler. Load/store/mov/inc/jeq/jump and perhaps a few others. Luajit implements its parser in pure assembly and I am not aware of an important platform that luajit runs on that zig goes. I do the vast majority of my programming in lua and _never_ run into bugs in the interpreter. I truly cannot think of a single problem that I think zig would solve better than luajit. Even if that did exist, I could embed the zig code in my lua file and use lua to drive the zig compiler and then call into the specialized code using the lua ffi. But the vast majority of code does not need to be optimized to the level of machine code where it is worth putting up with all of the other headaches that adopting zig will create. The hype around zig is truly reaching llm levels of disconnection from reality. Again, to believe in zig, one has to believe it will magically develop capacities that it does not presently have and for which there is no plan to actually execute besides vague plans of just wait.
- eps 1y agoSounds mostly like a documentation issue, or the lack of thereof.
- jeroenhd 1y agoBecause of how many parts of Zig change every other month, writing documentation doesn't seem to be a priority with Zig. The same way the Zig tutorial is just "here's a bunch of examples of Zig code" (that doesn't always compile on the latest version of the compiler), you're expected to read the source code for a lot of Zig standard library definitions. For a lot of simple calls, that works out pretty well, once you know all the tricks to Zig's syntax. A lot of requirements and implications are generally written out in very simple and short functions that are often logically named. Things like Allocators are pretty easy conceptually even if you probably don't want to write one yourself. It all breaks down when you start dealing with complex concepts. Zig's new I/O system looks a lot like Java's streams and wrappers and readers and writers, all wrapping around each other to make sending encrypted text over a secure channel as simple as output.write("hello"). I think the new I/O system combined with the lack of documentation about how to use it was a mistake. I'm not even sure if expressing a typing system as complicated as this in the Zig standard library is a good idea. The entire language runs on clear, concise, short and readable methods, and the new system doesn't seem idiomatic in that way.
- hardwaresofton 1y agoI'm not a Zig PM but the first obvious fix for the issues the OP wrote about is to write better documentation, including usage examples (the more the better, almost to a fault). Also doubles as a good time to reflect on whether the user is having to do too much. If the tradeoff was absolute performance/avoiding introducing load-bearing performance-lowering abstraction I think that goal was achieved, but DX may have gone out the window.
- brabel 1y agoYou’re not familiar with Zig’s culture, I guess. Complain about the lack of documentation and be prepared for the flood of “just read the stdlib code” helpful comments by pretty much everyone who writes Zig right now. Because most APIs are just as hard to use as in this post (check things like HTTP and even basic file system operations) only the strongest survive.
- hardwaresofton 1y agoYeah, thinking about this attitude positively, maybe it’s a feature — if only hard core people can comfortably figure it out, you get higher quality contributions? Not trying to imply that’s an explicit goal (probably instead just a resource problem), but an observation
- ksec 1y agoI think it is a trade off for between zig's development speed and documentation. It is Pre 1.0, extreme beta mode with lots of breaking changes. Generally speaking I think it is the right trade off for now. Purely inferring from Andrew and the Zig's team online character as I don't know them in person, I think they do care a lot of DX, things like compiling speed and tools. So I think once 1.0 come I won't be surprised if it will have extremely good documentation as well. And I would argue, writing good, simple, clear, detailed documentation is actually harder than writing code itself.
- LambdaComplex 1y ago
- 8s2ngy 1y agoI’m sorry, but any non-trivial Zig code gives me PTSD flashbacks of C. I don’t understand who Zig is targeting: with pervasive mutability, manual allocation, and a lack of proper sum types, it feels like a step back from languages such as Rust. If it is indeed a different way to write code, one that embraces default memory unsafety, why would I choose it over C, which has decades of work behind it? Am I missing some context? I’d love to hear it.
- ozgrakkurt 1y agoCompared to C: Discriminated unions, error handling, comptime, defer. Better default integer type casting, ability to choose between releaseSafe/releaseFast And probably other things. As for comparison to Rust, you do want very low level memory handling for writing databases as an example. It is extremely difficult to write low level libraries in Rust
- simonask 1y agoI think the argument is that it is also extremely difficult to write low level libraries in Zig, just as it is in C. You will just only notice the difficulty at some later point after writing the code, potentially in production.
- flohofwoe 1y ago> low level libraries in Zig, just as it is in C Did you write any Zig code yet? In terms of enforced correctness in the language (e.g. no integer promotion, no implicit 'dangerous' casts, null-safety, enforced error handling, etc...) and runtime safety (range-, nullptr-, integer-overflow-checks etc...), Zig is much closer to Rust than it is to C and C++. It "just" doesn't solve static memory safety and some (admittedly important) temporal memory safety issues (aka "use-after-free"), but it still makes it much harder to accidentially trigger memory corruption as a side effect in most situations that C and C++ let slip through via a mix of compile errors and runtime checks (and you get ASAN/UBSAN automatically enabled in debug builds, a debug allocator which detects memory leaks and use-after-free for heap-allocations (unfortunately not for stack allocations), and proper runtime stack traces - things that many C/C++ toolchains are still missing or don't enable by default). There is still one notable issue: returning a reference to stack memory from a function - this is something that many unexperienced Zig programmers seem to stumble into, especially since Zig's slice syntax looks so 'innocent' (slices look too similar to arrays, but arrays are values, while slices are references - e.g. 'fat pointers') - and which IMHO needs some sort of solution (either a compile time error via watertight escape analysis, or at least some sort runtime check which panics when trying to access 'stale' data on the stack) - and maybe giving slices their own distinct syntax that doesn't overlap with arrays might also help a bit.
- danieltanfh95 1y agoits bad because they are mixing what was supposed to just be execution boundaries into the overall runtime engine without making it explicit how to bridge between one and another.
- JaggerJo 1y agoZig would be my go to language for low level stuff. I think fact that Zig can be used as a C/C++ cross compiler is brilliant.
- latch 1y agoAuthor here. I finally got it working. I had to flush both the encrypted writer and then the stream writer. There was also some issues with reading. Streaming works, but it'll always return 0 on the first read because Writer.Fixed doesn't implement sendFile, and thus after the first call, it internally switches from streaming mode to reading mode (1) and then things magically work. Currently trying to get compression re-enabled in my websocket library. (1) https://github.com/ziglang/zig/blob/47a2f2ddae9cc47ff6df7a71060bbb3f5f20f2e8/lib/std/fs/File.zig#L1318 https://github.com/ziglang/zig/blob/47a2f2ddae9cc47ff6df7a71...
- dchest 1y agoHa, "Don't Forget to Flush" https://www.youtube.com/watch?v=f30PceqQWko https://www.youtube.com/watch?v=f30PceqQWko
- jenadine 1y agoThat's why I like RAII.
- AndyKelley 1y agoIt's a bug to flush (fallible operation) in a destructor (infallible operation).
- oconnor663 1y agoI know you've thought carefully about these issues, but still it can't be that simple, can it? Closing a file or a socket is a fallible operation too.
- AndyKelley 1y agoWrong.
- MrResearcher 1y ago
- jedisct1 1y agoThe new I/O interface makes printing a simple “Hello, world!” more complicated, but once you get used to it, the design is actually very clean, versatile, and future-proof. Since 0.15, though, I feel too dumb for Zig’s ArrayList.
- simonask 1y agoIs it future-proof though? Last I saw, it relied on some yet-to-be-determined design for compiling async variants of everything that uses IO, and it was still unclear whether it was possible at all to support dynamic dispatch. My info could be outdated - I don't follow Zig very closely, but I am curious.
- kristoff_it 1y agoThe Reader/Writer changes are perfectly compatible with the upcoming async I/O stuff and you won't need to change any code that just deals with streams. No promises about potential future changes though :^)
- throwawaymaths 1y agoi think hello world is actually easier? getstdout doesnt exist anymore and its equivalent is nonfailable.
- xmorse 1y agoIf you are too dumb for it I don't have any hope
- laserbeam 1y agoI… will not update my zig side projects to 0.15.x. I can see why Andrew wanted to release this, and I can appreciate getting the new Io in people’s hands… but it’s merely a few weeks after merging massive amounts of breaking changes on readers and writers. For those working on the standard library, it’s a great thing. For one like me who casually uses zig, it feels like waiting for 0.16.0 for most of the IO dust to settle is the right thing to do.
- debo_ 1y agoIf you're a language called Zig, I guess you sometimes have to Zag.
- audunw 1y agoEven Loris Cro one of the Zig core members, mentioned in a very recent interview that he’ll wait for all the fallout of the IO changes to settle before updating and continuing work on his project using Zig. The future looks bright after that though. Both Andrew and Loris seem to think this is the last major breaking change, so I hope we can see a 1.0 not too long after. The biggest uncertainty now is what the consequences of (re-)introducing stack-less coroutines will be.
- Galanwe 1y ago> Both Andrew and Loris seem to think this is the last major breaking change, so I hope we can see a 1.0 not too long after. Well I mean the standard library still needs a _lot_ of work IMHO. Process management for instance is at a stage where it's barely usable for simple use cases.
- j1elo 1y ago> To convert the Stream.Reader to an std.Io.Reader, we need to call its interface() method. To get a std.io.Writer from an Stream.Writer, we need the address of its &interface field. This doesn't seem particularly consistent. That made me think of how that change would be received in Go (probably would be discarded). They way they approach changes in extremely deep analysis and taking as much time as it needs to avoid mistakes and reach a consistent solution (or as close as possible). This has been my favorite for a while: https://github.com/golang/go/issues/45624 https://github.com/golang/go/issues/45624 4 years to decide on something relatively minor, that right now can be done with a bit of a one-liner extra work. But things need to be well thought out. Inconsistencies are pointed out. Design concerns are raised. Actual code usage in the real world are taken into account... too slow for some people, but I think it's just as slow as it needs to be. The final decision is shaping out to be very nice.
- josephg 1y agoRust is the same. It grinds my goat a little how many useful features are implemented - but only available in nightly rust. Things like generators. But when rust ships features to stable, they’re usually pretty well thought through. I’m impatient. But the rust language & compiler teams probably have the right idea.
- hu3 1y agoI beg to differ. Rust async implementation is contentious and criticized often. Sometimes you just miss the mark despite pondering about it for a while. Same with Go.
- josephg 1y agoYeah async rust is definitely the exception. That and Pin, which in my opinion totally missed the mark. The feature rust needs is the ability to have self reference in a struct. Pin is a hacky, inadequate half solution.
- mwcampbell 1y ago
- noobermin 1y agoHaving seen the posts about the new IO interface, I decided to steer clear from Zig. Looks like that fortuitious instinct was proven valid as this looks more and more like the verbosity from pre C++11 for different reasons but with a similar result. This pattern (new language evolves to be as complex as the languages it was supposed to replace) seems familiar.
- ivanjermakov 1y agoAs being one of the post authors you mentioned, I don't think such posts should scare people from trying it out. Zig team is eager to discuss and break things if a better solution is found. Such approach is not a great fit for those who treat Zig as a future job opportunity, but for personal and small-team projects it's _already_ a neat language with clear goals and great tooling.