57 points by signa11 3 days ago | 9 comments
hansvm 3 days ago
> Every object (being constant or variable) that you declare in Zig must be used in some way.
This is true for eagerly evaluated code (function bodies) and false for lazily evaluated code (struct definitions). That latter thing already trips people up because you can have full-on compiler errors defined somewhere and never know because they're never used (depending on your build mode, there will be some root artifacts -- tests for test builds, main for executable builds, export functions for library builds, transitively visible public members for modules -- and only code transitively referenced by those artifacts is compiled). Explicitly stating the opposite is going to confuse some beginners.
> How Object-Oriented programming can be done in Zig through struct declarations
That example is only very lightly object oriented. It doesn't cover runtime polymorphism or inheritance (both possible and occasionally useful, like in the std Allocator definition) or compiler-checked subtyping (not really possible in any useful manner). It's data classes with member functions rather than what a lot of people call OOP. I think the thing actually being taught is probably at the right level for the book, but it should be presented as what it is, _perhaps_ mentioning those other concepts.
> In order to debug your program through a debugger, you must compile your source code in Debug mode
This isn't really true either, and some things are very hard to debug when you're not in a release mode. You just need to ensure the appropriate debug symbols are included, and you can toggle those build options in any build mode.
sebazzz 2 days ago
signa11 3 days ago
she is mostly hacking on open-source apple-gpu drivers (on apple silicon platform) for linux (not that she needs any introduction in these parts)
hansvm 3 days ago
That said, you can write an inaccessible reference cycle that never calls drop() in Rust just as well as you can in most non-GC languages. Leaks are explicitly defined as "safe" in Rust, and IME they're quite common in the wild. Even major projects like Actix had known leaks for several major versions, and you still need to run sanitizers and whatnot to probabilistically find them.
Interestingly, the notion of dropping precisely when something goes out of scope is itself a performance footgun. The pattern of "defer" in Zig encourages thinking in terms of lifetimes and groups of obects, which is much cheaper and easier to reason about.
You can absolutely do that in Rust too, but the language defaults encourage a slightly different programming model, so I see more code that's distasteful to my eyes in that respect in Rust codebases.
woodrowbarlow 3 days ago
i actually like C (despite its warts) because the mental model of the compiler is small and i can usually reason correctly about what will happen.
in rust, it's certainly possible for an inexperienced developer to attain the same level of intuitive reasoning, but the mental model for the compiler is orders of magnitude larger. ultimately, rust wants the user to trust the compiler, rather than understand the compiler.
zig embraces the small mental model and gets rid of almost every C wart (in my eyes). fewer built-in guarantees, but less magic.
Brian_K_White 1 day ago
I like to call it UB, Unexpected Behavior, pretty much just as bad as the usual UB.
pseudony 2 days ago
I wouldn't pick my languages based on someone else's hot take, or any Manga avatar, actually. I also honestly doubt "Lina" is unbiased here. They sound like they leaned in heavy from C++, good on them. But many who are drawn to zig, like me, rejected C++ in the first place. Rust does seem like a nice step up for systems programmers who used C++, namely because it seems to expand on and refine so many ideas from there. But if you disagree with the kitchen-sink approach to language features, then Rust might not be for you anyway.
menthe 3 days ago
> All this stuff is just done automatically in Rust. If you have to write out the code by yourself, that's more work, and a huge chance for bugs. The compiler is doing some very complex tracking to figure out what to drop when and where. You'd have to do that all in your head correctly without its help.
What prevents anyone from dedicating a Zig memory allocator to the job (and all of its subtasks), and simply freeing the entire allocator at the end of the job? No baby-sitting needed.
Or if the mindset is really to be assisted, because “very complex” and too “much work”, may as well use a garbage collected language.
> It's knowing the compiler is on your side and taking care of all this that makes it magical.
Until you got used to it, and trusted it so much, and it suddenly misses something - either after a compiler update, or after some unsupported code introduced, and that shit takes down prod on a Friday. I’m not going to take the chance, thank you, I can call free() and valgrind.
TUSF 2 days ago
Given the whole ecosystem is built around the Allocator interface, it's entirely feasible for the consumer of a library to pass in a Garbage Collecting allocator, and let it do the job of deciding what gets dropped or not.
Downside is that this is all at runtime, and you don't get the compile-time memory management that Rust has.
3 days ago