hansvm 6 hours ago

After reading a few chapters and skimming the rest, this looks just fine. It's about the right level for somebody picking up a new language (when the language gets much more popular I'd like to see something similar targeting new programmers), and the writing fits together nicely. There are a lot of small things that aren't quite right though, and some of those I'm not sure are even appropriate simplifications pedagogically. A smattering of examples:

> 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.

signa11 6 hours ago

for those debating rust-vs-zig, here is asahi-lina's take: https://vt.social/@lina/113327855904055160

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 4 hours ago

    I'm glad Rust is working well for them. Everyone should use tools they love.

    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 4 hours ago

    my take --

    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.

  • menthe 5 hours ago

    Meh, typical overblown “take” ihmo.

    > 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.