‹ BackHN Continuity

Thread

What Zig felt like, coming from Rust

282 points · 351 comments · ksec

  1. plqbfbv · · focus · HN ↗
    Maybe I'm not that deep into programming, but I don't understand the hype about Zig?

    I programmed in rust a bit and can't say I'm an expert, but in my view rust mostly-solved the memory management problem at compile time and without a GC, and it works very well. The biggest con and cost I've always seen repeated so far is that "it's slow to compile", and I get that, if you're past 250 crates the final --release link tends to become noticeable, but there were improvements to incremental compilation.

    On the other hand - looking at the syntax from this post - Zig feels a blend of javascript, python and golang syntax that still requires memory management. So a nicer-written C that inherits all the issues from C? From the post: no functional programming, data mutation, memory leak, double-free, memory corruption.

    Personally I'd rather trade a couple minutes of final link every time when this is the other option.

    1. pron · · focus · HN ↗
      > I don't understand the hype about Zig?

      As a long-time low-level programmer, and as someone working on a popular mainstream language, I find Zig fascinating, and I also think it addresses a long-standing problem in low-level programming. I'll get to the problem later, but the fascinating part is its use of partial evaluation (comptime) as a single coherent mechanism that replaces a myriad of other partial-evaluation mechanisms (macros, templates/generics, constexprs). That one mechanism is the core of the language, like macros are in lisps, and that design - whether you like it or not - is revolutionary. It's never been done before (other languages have partial evaluation mechanisms that are almost as general, but they're offered in addition to, not as a replacement of, other features).

      > rust mostly-solved the memory management problem at compile time and without a GC

      "Mostly" does a lot of work here because 1., if you look at the implementation of very efficient, possibly specialised data structures - the very thing you reach for a low-level language for - they typically require unsafe, and 2., it still suffers from the problem C++ has had for decades, which is that over time, as program changes and evolves over years, things tend to drift toward the more general mechanisms that rely on malloc/free on an individual objects, and the program gets slower and slower (huge runtimes like TCMalloc help, but not enough, because they can't move pointers). This problem, of programs that start out fast, but after five or ten years of evolution need to spend a lot of effort to remain fast, is one of the things moving collectors were designed to solve, but they require moving pointers, which doesn't work in low-level languages that are not meant to have an FFI layer between them and the hardware.

      To compete with the performance of moving GCs, which allocate through bumping a pointer, like on the stack, and free memory in bulk, low-level languages need to rely on arenas (which work based on a similar principle), and Zig is the first language that makes arenas almost user-friendly and hopefully sufficiently composable to withstand program evolution. Of course, time will tell how well this works in practice.

      1. treyd · · focus · HN ↗
        > the very thing you reach for a low-level language for - they typically require unsafe

        There's a formal proof asserting that if you keep up the safety invariants within an unsafe region then that will not infect other code, even in the presence of arbitrary other correctly-written unsafe blocks.

        This means you can build abstractions on top of these low-level primitives to keep it contained, so consumer code never has to even think about or know there's unsafe blocks in it. The type system lets you build very powerful abstractions so these go a long way.

        There's a lot of woo-woo scare quoting around how much you actually have to use unsafe code in Rust. It's fairly uncommon to actually have to reach for them in practice. Most of my usage ends up being things like converting a &[u8] to a &str when I know it's already valid UTF-8 so I want to skip the linear-time validity check. Very rarely do I have to build data structures with complicated pointer juggling, because there's often a library that already does what I need!

        > which is that over time, as program changes and evolves over years, things tend to drift toward the more general mechanisms that rely on malloc/free on an individual objects, and the program gets slower and slower

        What are you talking about? I've never encountered this and I've been using Rust for 10 years.

        1. dnautics · · focus · HN ↗
          > There's a formal proof asserting that if you keep up the safety invariants within an unsafe region then that will not infect other code, even in the presence of arbitrary other correctly-written unsafe blocks.

          In general "unsafe" does not compose.

          "if you keep up the safety invariants within an unsafe region"

          This condition is doing a lot of heavy lifting.

          1. treyd · · focus · HN ↗
            Here&#x27;s an article about the research on it which lays out the properties in simple terms: <a href="https:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2016&#x2F;10&#x2F;02&#x2F;observational-equivalence-and-unsafe-code&#x2F;" rel="nofollow">https:&#x2F;&#x2F;smallcultfollowing.com&#x2F;babysteps&#x2F;blog&#x2F;2016&#x2F;10&#x2F;02&#x2F;obs...

            I&#x27;m curious why you think that statement is doing heavy lifting. It&#x27;s much easier to write and verify that a few lines of code are correct than it is to write and verify that an entire program is correct. But that&#x27;s the norm in C and Zig, and historically people haven&#x27;t been very good at it. That&#x27;s why we try to do it as little as possible.

            1. pron · · focus · HN ↗
              Many more C programs have been verified than Rust programs. Also, Zig&#x27;s spatial and memory safety is as good as Rust&#x27;s, so it&#x27;s not really similar to C at all.

              The reason it&#x27;s not &quot;the norm&quot; is that (especially with spatial safety taken care of), not every line is equally dangerous at all. Still, there&#x27;s no doubt that more guarantees help, but that is only when all other things are equal. If you pick a low-level language for mostly low-level things, so Rust doesn&#x27;t offer safety for the trickiest code, and furthermore it makes certain things harder to see because the language is more complicated, then things become much less clear. Obviously, when the vast majority of the trickiest, most important code doesn&#x27;t need to be low-level, Rust would probably be safer on the whole, but in such situations I see no reason to choose either Rust or Zig. You need to choose a low-level language if the core of what you&#x27;re doing needs to be low-level.

              1. aw1621107 · · focus · HN ↗
                &gt; Also, Zig&#x27;s spatial and memory safety is as good as Rust&#x27;s

                Is there a word missing before &quot;memory&quot;? Seems odd to specifically call out spatial memory safety when memory safety subsumes it.

                1. steveklabnik · · focus · HN ↗
                  Usually people say “spatial” vs “temporal”.
                2. ngrilly · · focus · HN ↗
                  That&#x27;s because Zig offers spatial memory safety (e.g. buffer overflows and index out of bounds), but no temporal memory safety (e.g. use-after-free). I suppose the &quot;and&quot; before &quot;memory safety&quot; is a typo.
                3. pron · · focus · HN ↗
                  sorry, the &quot;and&quot; was a typo
Open on Hacker News to reply ↗

Unofficial Hacker News client; not affiliated with Y Combinator.