← Back to context

Comment by pron

5 years ago

You're looking at the details, while I look at the overall "feel" and find them almost indistinguishable. They're both low-level languages -- and so, like all low-level languages, suffer from low-abstraction, i.e. the difficulty to hide internal implementation details from consumers behind APIs -- that decided to invest their complexity budget to get the appearance of high-level code once you read it on the page (while the difficulty of changing it is the same as with all low-level languages), and don't hesitate to employ a fair bit of implicitness, grow a large set of features, and let compilation be slow. The details of how they do that are less important; what's most apparent is their shared design philosophy of low-level programming (although I think that Rust improves on C++ and certainly cleans it up). Zig offers a radically different approach, and one that is also radically different from C's philosophy.

I don't think your critiques are accurate, but anyway, the "similarity" here is that you have the same high-level critique of both languages. This does not make Rust "pretty darn similar to C++".

For me, memory and data-race safety and absence of undefined behavior are critical features, but it would be misleading if I were to go around saying "C, C++ and Zig are all pretty darn similar".

  • > the "similarity" here is that you have the same high-level critique of both languages.

    The similarity is that they both espouse the very same design philosophy for low-level programming. It's a pretty big similarity.

    > For me, memory and data-race safety and absence of undefined behavior are critical features, but it would be misleading if I were to go around saying "C, C++ and Zig are all pretty darn similar".

    It would be misleading, because memory safety and undefined behaviour in Zig is much closer to Rust than to C++. Even where it's not the same as Rust, it's still very different from C/C++. Safety and correctness are as emphasised in Zig as in Rust; they just go about achieving them differently. It is not clear at all which of them achieves correctness better.

    • > Safety and correctness are as emphasised in Zig as in Rust

      This is so far from true I cannot take you seriously.

      Zig doesn't have any kind of lifetime analysis, so it's as vulnerable to use-after-free/dangling pointers as C and C++ are. That alone rules out Zig from ever being considered "memory safe" in any meaningful sense.

      [Yes, I'm aware of GeneralPurposeAllocator, but that is not something you want to ship in production. "Never reuse any virtual address space" is a disaster for the OS (VMA fragmentation, TLB shootdown IPIs) and the hardware (TLBs, caches). That's why no-one ships such a thing in production for C/C++. GeneralPurposeAllocator will no doubt be useful for debugging (though less effective than ASAN or Valgrind) but safety in production is the game here; ASAN doesn't make C/C++ "memory safe".]

      Zig also allows data races so Zig programs can have undefined behaviour via data races on non-atomic values. Again, this cannot be fixed.

      Even smart pointers (e.g. reference counting) are nasty in Zig. Zig doesn't have destructors so cleaning up an owning pointer or a refcounting pointer requires developers to write manual "defer" statements. Worse, these only work at function scope so you also have to write manual cleanup code for every data structure containing a smart pointer. Without idiomatic smart pointers Zig will likely be more prone to UAF bugs (and leaks) than C++.

      5 replies →