I don't understand how the things presented in this article are surprising. Zig has several nice features shared by many modern programming languages?
I don't understand how the things presented in this article are surprising. Zig has several nice features shared by many modern programming languages?
That the author feels the need to emphasize this means either that they haven't paid attention to modern languages for a very long time, or this article is for people who haven't paid attention to modern languages for a very long time.
Type inference has left academy and proliferated into mainstream languages for so many years that I almost forgot that it's a worth mentioning feature.
> One is Zig’s robustness. In the case of the shift operation no wrong behavior is allowed and the situation is caught at execution time, as has been shown.
Panicking at runtime is better than just silently overflowing, but I don't know if it's the best example to show the 'robustness' of a language...
I'm not even sure I'd call this type inference (other people definitely do call it type inference) given that it's only working in one direction. Even Java (var) and C23 (auto), the two languages the author calls out, have that. It's much less convenient than something like Hindley-Milner.
It’s not common in lower level languages without garbage collectors or languages focused on compilation speed.
“Low-level” languages — Rust, C++, D
> what the heck does it matter what "much of the standard library uses" to this issue?
It matters in that most people looking for a low level manually memory managed language won’t likely choose D, so for the purposes of “is this relatively novel among lower level, memory managed languages” D doesn’t fit my criteria.
> Even C now has type inference. The plain fact is that the claim is wrong.
Almost no one is using C23 yet.
What Zig really does is make systems programming more accessible. Rust is great, but its guarantees of memory safety come with a learning curve that demands mastering lifetimes and generics and macros and a complex trait system. Zig is in that class of programming languages like C, C++, and Rust, and unlike Golang, C#, Java, Python, JS, etc that have built-in garbage collection.
The explicit control flow allows you as a developer to avoid some optimizations done in Rust (or common in 3rd party libraries) that can bloat binary sizes. This means there's no target too small for the language, including embedded systems. It also means it's a good choice if you want to create a system that maximizes performance by, for example, preventing heap allocations altogether.
The built-in C/C++ compiler and language features for interacting with C code easily also ensures that devs have access to a mature ecosystem despite the language being young.
My experience with Zig so far has been pleasurable. The main downside to the language has been the churn between minor versions (language is still pre-1.0 so makes perfect sense, but still). That being said, I like Zig's new approach to explicit async I/O that parallels how the language treats Allocators. It feels like the correct way to do it and allows developers again the flexibility to control how async and concurrency is handled (can choose single-threaded event loop or multi-threaded pool quite easily).
I don't think there's is any significant different here between zig, C and Rust for bare-metal code size. I can get the compiler to generate the same tiny machine code in any of these languages.
C, yes, you can compile C quite small very easily. Zig is like a simpler C, in my mind.
Zig on the other hand does lazy evaluation and tree shaking so you can include a few features of the std library without a big concern.
IIRC there's also a mutex somewhere in there used to workaround some threading issues in libc, which brings in a bespoke mutex implementation; I can't remember whether that mutex can be easily disabled, but I think there's a way to use the slower libc mutex implementation instead.
Also, std::fmt is notoriously bad for code size, due to all the dyn vtable shenanigans it does. Avoid using it if you can.
Regardless, the only way to fix many of the problems with std is rebuilding it with the annoying features compiled out. Cargo's build-std feature should make this easy to do in stable Rust soon (and it's available in nightly today).
Zig is a good language. So are Rust, D, Nim, and a bunch of others. People tend to think that the ones they know about are better than all the rest because they don't know about the rest and are implicitly or explicitly comparing their language to C.
Of course both Zig and Rust are good languages. But my experience, and I believe your experience will be too if you try to compile programs of similar complexity using standard practices of each language, is that Zig compiles much more compactly in .ReleaseSmall mode than Rust does even with optimization flags, which makes it more ideal for embedded systems, in my opinion. I learned this on my own by implementing the same library in both languages using standard default practices of each.
Of course, at the desktop runtime level, binary size is frequently irrelevant as a concern. I just feel that since Zig makes writing "magic" code more difficult while Rust encourages things like macros, it is much easier to be mindful of things that do impact binary size (and perhaps performance).
This is not true. Zig, D, and Nim all have full-language interpreters built into the compiler; Rust does not. Its macros (like macros generally) manipulate source tokens, they don't do arbitrary compile-time calculations (they live in separate crates that are compiled and then run on source code, which is very different from Zig/D/Nim comptime which is intermixed with the source code and is interpreted). Zig has no macros (Andrew hates them)--you cannot "generate code" in Zig (you can in D and Nim); that's not what comptime does. Zig's comptime allows functions written in Zig to execute at compile time (the same functions can also be used to run at execution time if they only use execution-time types). The Zig trick is that comptime code can not only operate on normal data like ints and structs, but also types, which are first class comptime objects. Comptime code has access to the TypeInfo of types, both to read the attributes of types and to create types with specified attributes, which is how Zig implements generics.
Or it's hyperbolic.
I got that impression as well.
Xi's impressed about types being optional because they can be inferred.
That's ... hardly a novelty ...
Funny they mention Java that has got type inference few years now. Even C got a weaker version of C++'s auto in C23.
Zig feels like one of the few programming languages that mostly just avoids gigantic blunders.
I have some beefs with some decisions, but none of them that are an immutable failure mode that couldn't be fixed in a straightforward manner.