6 ms·
Some of Zig's ideas fascinate me, both the great low-level concepts (e.g. arbitrary-sized ints), but much more than that, the high level concepts. Particularly
by tobz1000 6y ago
Some of Zig's ideas fascinate me, both the great low-level concepts (e.g. arbitrary-sized ints), but much more than that, the high level concepts.
Particularly great is Zig's handling of both macros and generic types, the answer to both of which seems to be: just evaluate them at compile-time with regular functions, no special DSL or extra syntax. Andrew mentions in the video a big drawback of this system - implications for IDE complexity and performance. I imagine the performance side of this could be (maybe is?) mitigated by limiting recursion depth/loop counts for compile-time work.
I'm not particularly interested in taking on a language with manual memory management and the responsibilities it entails, but I would love to have access to Zig's compile-time capabilities, if it were available with some more memory safety.
- pron 6y agoZig gives you memory safety (or, rather, will ultimately do that), but it does so in a way that's different from both languages with garbage collection (whether tracing or reference-counting) or with sound type-system guarantees a-la Rust. It does so with runtime checks that are turned on in development and testing and turned off -- either globally or per code unit -- in production. You lose soundness, but we don't have sound guarantees for functional correctness, anyway, and given that Zig makes testing very easy, it's unclear whether a particular approach dominates the other in terms of correctness.
- renaicirc 6y ago> You lose soundness, but we don't have sound guarantees for functional correctness, anyway This sounds like "we can't guarantee the most important thing, so it's unclear whether it's useful to guarantee this other thing," but that's a bizarre statement, so am I misinterpreting?
- pron 6y agoIt means that there's a complex tradeoff between making sound guarantees and providing correctness in other ways, a tradeoff that all languages make anyway, each finding its own preferred sweet spot, and that we don't know if, say, Rust's sweet spot yields better correctness than Zig's.
- TinkersW 6y agoThat is the same approach used in many C++ projects
- renaicirc 6y agoThen I guess the obvious question is: has it worked well for those projects?
- TinkersW 6y agoIt obviously isn't as safe as Rust, but I think it works well enough for something like gamedev(where absolute safety isn't required). For memory related issues I find it sufficient. One aspect where it is probably not as good as Rust is for threading related issues, as it relies on inserting runtime checks which may or may not trigger depending on the number of threads attempting access.
- pron 6y agoBut to do that you can only use a subset of C++ (e.g. you can't use arrays nor pointer arithmetic). This works for all of Zig, except for some very specific, clearly marked, "unsafe" operations.
- TinkersW 6y agoIt works with arrays if you stick with std::array & std::span like constructs. It also works with iterators-generally by sticking some extra data in the iterator in dev builds, so it can check for out of bounds access. If I do have some code that uses C pointers + size, I'll insert some dev build assertions.
- pron 6y agoSure, and then when you enforce that you address the third most bothersome thing for me in C++, leaving you only with the top two (for me): a complex language and slow compilation.
- azakai 6y agoMy understanding is that Zig goes further than that. In particular it just added a safe allocator suitable for production, https://github.com/ziglang/zig/pull/5998 https://github.com/ziglang/zig/pull/5998 edit: For more details, see https://ziglang.org/#Performance-and-Safety-Choose-Two https://ziglang.org/#Performance-and-Safety-Choose-Two
- vmchale 6y agoThat's not on par with linear or affine types.
- pron 6y agoWhen compared in isolation, yes. But such mechanisms aren't free; they add to both language complexity and compilation time, two things that can have a negative impact on correctness. So it's impossible to say which approach leads to more correct programs overall without empirical study. We see similar tradeoffs of soundness in formal verification as well. We're not talking about exactly the same thing here (because affine type safety is compositional) but the general principle is the same: soundness has a cost, and it is not necessarily the most efficient way of achieving a required level of correctness. Anyway, I think that both Rust and Zig have very interesting approaches to safety, but I don't think we know enough to claim one is more effective than the other at this time.
- edflsafoiewq 6y agoDoes zig have an answer to RAII yet?
- pron 6y agoRAII is not a question. Zig prefers explicitness, i.e. by looking at a subroutine you know exactly which code is called, its approach to releasing resource uses defer.
- edflsafoiewq 6y agoThe question is how to do automatic resource management. There are no checks of any sort, runtime or not, to help you here (correct me if I'm wrong). RAII is not precluded by explicitness, you could require all values that require cleanup to be syntactically marked in some way and it would still be RAII. defer also cannot handle resources whose lifetimes do not correspond to nested scopes (eg. the elements of an ArrayList) like RAII or a GC can.
- pron 6y ago> RAII is not precluded by explicitness, you could require all values that require cleanup to be syntactically marked in some way and it would still be RAII. I think this one is TBD. > defer also cannot handle resources whose lifetimes do not correspond to nested scopes (eg. the elements of an ArrayList) like RAII or a GC can. Yep, defer won't work if there is no known lifetime scope, but I think this one is actually a good tradeoff to make in a low-level language. Don't get me wrong -- I love tracing GCs and think that they're the right choice for the vast majority of application software, plus there have been great strides made in GC capabilities in the past few years, but in the domains where low-level languages are appropriate there is a different set of constraints. Low-level programming is not like high-level programming, and IMO it's wrong to even try to make them look alike.
- int_19h 6y ago> defer also cannot handle resources whose lifetimes do not correspond to nested scopes It can, it's just more explicit about it. In a language with destructors, you'd do RAII here by having a list destructor that cleans up each element in turn. In a language with defer, the same destructor becomes a regular function that you'd invoke in the deferred expression.
- aidenn0 6y agoValgrind on C is the closest thing I've worked with in terms of what Zig offers. My experience is that Rust's approach is definitely better in terms of correctness than using valgrind during testing. My intuition is that the advantages Zig brings to the table will not tip the balance. That being said, the choice Zig makes is absolutely the right one. Rust fills the niche of a better and more correct C++ without fixing the issues of slow compilation and language complexity. Zig fixes so much of what's wrong with C without abandoning the advantages of language simplicity and locality of reasoning. I love Zig, but need a medium sized non-work project for it.
- dnautics 6y agoIt's pretty easy to use Zig as the low level for languages which can take a C FFI. Self-promotion: I wrote zigler which integrates zig as inline code in elixir.
- vips7L 6y agoI've been slowly replacing the C files of xv6 with some zig. It was surprisingly easy with the generated header files to use zig from within the C part.