Zig tries very hard to stay (relatively) simple, make things possible, but not hide all the important details.
And once a language designer adds ways (and a programmer culture) to hide things - it becomes very hard to follow the code.
Zig attacks this design space from a low abstraction and explicit flow point of view.
Best C++ code that deals with low level details is as least abstracted as possible.
One of the reasons C is used for writing operating systems kernels is that it doesn't hide details. Imagine Linux kernel written in OOP way with design patterns and SOLID principles. :)
Doesn't sound that terrible to me.
Just out of interest, do you think `*(int*)(0x12345678) = 0;` is the best way to do memory-mapped IO? That's least abstracted.
I've actually encountered seasoned embedded devs advocating using the magic number in this very case. Never really understood why. It was some combination of "abstractions bad" and "I want to be able to check all adresses against my printed dead-tree documents while debugging "...
Of course noone really believes "all abstractions bad", but I wonder why some people still claim that.
Wrong way (according to you): Compute factorial using AVX intrinsics
Best way (according to you): Make a factory class AbstractMathFormulaCalculatorBuilderFactory to instantiate a builder class AbstractMathFormulaCalculatorBuilder which can build an AbstractMathFormulaCalculator, from which you derive a FactorialCalculator in which you use an AbstractMathFormulaExecutor, built with an AbstractMathFormulaExecutorBuilder, generated by AbstractMathFormulaExecutorBuilderFactory.
1. https://ziglang.org/learn/overview/#small-simple-language
If you don't like using abstractions, but if you like instead to make everything explicit, that is of course your prerogative. But denying that there is a right abstraction will just keep you from finding it. It doesn't change the fact that there often is one.
Going after the right abstraction takes time, and it might be just too expensive in your context, or your context may actually make abstraction infeasible. So in my opinion, it is all about trying to get into a position where experimenting with abstractions becomes cheap and economical. In principle, we should be in a much better position today in that respect than, say, 30 years ago.
That's not quite the same thing as 'personal preference', where the right answer is by definition whatever I think is right. It's possible for me to think that XYZ abstraction or lack-of-abstraction works well for me, when in fact there's some other approach would that work better if I took the time to learn how it worked. Maybe I just haven't heard of that approach, or maybe I'm lazy or inexperienced or don't have the time to learn. People always think they're more unique than they really are; compare to the concept of "learning styles" which keeps being debunked.
But surely there is some legitimate variation.
People should try to use Zig more like C and less like Python, Ruby or Java. If you miss abstract factories, builders, observers, visitors, decorators, maybe Zig isn't for you.
The article seems to have accomplished what they needed with Zig's error handling, they just quibbled over the syntax.
Personally, I love Zig's error handling.
You are, of course, free to write and use your own error type and handle it however you like, just as in C, but you won't get to use the special error handling syntax Zig has which relies on errors just being integers.
Or, as was done here, you can get the information you wanted to include with the error out in any number of other ways. You could have an error stack you push string pointers too, or use logging, etc. Zig just doesn't do that for you because, again, Zig philosophically doesn't allocate willy-nilly.
That's likely not the reason. The above article links to a Github issue in which people have been discussing various proposals for handling payloads since 2019, and not a single time it was ruled out because of allocations as those could be handled the same way as anywhere else.
Not to mention in many situations an error payload wouldn't necessitate an allocation. For example just allowing a single integer as payload in a parser would already be a huge help. If the language's standard library won't even return a position for JSON parsing errors I'd consider that a problem. Imho it is a mistake to give errors special syntax features without any way of expanding them.
An error is an abstraction Zig has chosen to provide over an integer. Without discarding any part of their philosophy, they can make this custom abstraction a bit more useful by allowing tagged unions to be errors.
Not allocating has nothing to do with not having errors. You can have tagged union errors without any allocation. Rust has them.
I don't want to build too many either. I prefer to build just the right amount of abstractions. Sounds though like Zig makes that difficult, so at least for me, it is a hard pass.
But then again, it's a matter of perspective.
Iirc you can handle allocation failures there now too, which I have often seen being criticized
:^)
A barber's razor is the perfect tool for the trade, together with a sharpening stone.
The Go equivalent would be a blade with two dull sides.
“The key point here is our programmers are Googlers, they’re not researchers. They’re typically, fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They’re not capable of understanding a brilliant language, but we want to use them to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt.”
-- Rob Pike