judofyr 2 hours ago

This is one the reasons I find it so silly when people disregard Zig «because it’s just another memory unsafe language»: There’s plenty of innovation within Zig, especially related to comptime and metaprogramming. I really hope other languages are paying attention and steals some of these ideas.

«inline else» is also very powerful tool to easily abstract away code with no runtime cost.

  • chrismorgan an hour ago

    What I’ve seen isn’t people disregarding Zig because it’s just another memory-unsafe language, but rather disqualifying Zig because it’s memory-unsafe, and they don’t want to deal with that, even if some other aspects of the language are rather interesting and compelling. But once you’re sold on memory safety, it’s hard to go back.

    • Sytten an hour ago

      This is really the crust of the argument. I absolutely love the Rust compiler for example, going back to Zig would feel a regression to me. There is a whole class of bugs that my brain now assumes the compiler will handle for me.

      • pron 32 minutes ago

        Problem is, like they say the stock market has predicted nine of the last five recessions, the Rust compiler stops nine of every five memory safety issues. Put another way, while both Rust and Zig prevent memory safety issues, Zig does it with false negatives while Rust does it with false positives. This is by necessity when using the type system for that job, but it does come at a cost that disqualifies Rust for others...

        Nobody knows whether Rust and/or Zig themselves are the future of low-level programming, but I think it's likely that the future of low-level programming is that programmers who prefer one approach would use a Rust-like language, while those who prefer the other approach would use a Zig-like language. It will be intesting to see whether the preferences are evenly split, though, or one of them has a clear majority support.

  • diegocg 2 hours ago

    As someone who uses D and has been doing things like what you see in the post for a long time, I wonder why other languages would put attention to these tricks and steal them when they have been completely ignoring them forever when done in D. Perhaps Zig will make these features more popular, but I'm skeptic.

    • brabel an hour ago

      I was trying to implement this trick in D using basic enum, but couldn't find a solution that works at compile-time, like in Zig. Could you show how to do that?

  • pron 41 minutes ago

    > just another memory unsafe language

    Also, treating all languages that don't ensure full memory safety as if they're equally problematic is silly. The reason not ensuring memory safety is bad is because memory unsafety as at the root of some bugs that are both common, dangerous, and hard to catch. Only not all kinds of memory unsafety are equally problematic, Zig does ensure the lack of the the most dangerous kind of unsafety (out-of-bounds access) while making the other kind (use-after-free) easier to find.

    That the distinction between "fully memory safe" and "not fully memory safe" is binary is also silly not just because of the above, but because no lanugage, not even Java, is truly "fully memory safe", as programs continue to employ components not written in memory safe languages.

    Furthermore, Zig has (or intends to have) novel features (among low-level languages) that help reduce bugs beyond those caused by memory unsafety.

  • Ygg2 2 hours ago

    > «inline else» is also very powerful tool to easily abstract away code with no runtime cost.

    Sure, but you lose the clarity of errors. The error wasn't in `comptime unreachable` but in `inline .a .b .c`.

    • jeltz 2 hours ago

      I disagree, I would say the error is in "comptime unreachable" or maybe the whole "switch (ab)".

    • binary132 36 minutes ago

      Adding a new case is legitimate, failing to handle it (by reaching unreachable) is an error.

veber-alex 15 minutes ago

I don't understand. Isn't this only useful if the value you match on is known at compile time?

spiffyk 2 hours ago

This post shows how versatile Zig's comptime is not only in terms of expressing what to pre-compute before the program ever runs, but also for doing arbitrary compile time bug-checks like these. At least to me, the former is a really obvious use-case and I have no problem using that to my advantage like that. But I often seem to overlook the latter, even though it could prove really valuable.

  • dwattttt 2 hours ago

    I love the idea, but something being "provable" in this way feels like relying on optimisations.

    If a dead code elimination pass didn't remove the 'comptime unreachable' statement, you'll now fail to compile (I expect?)

    • anonymoushn 2 hours ago

      A lot of Zig relies on compilation being lazy in the same sort of way.

      • dwattttt 2 hours ago

        For the validity of the program? As in, a program will fail to compile (or compile but be incorrect) if an optimisation misbehaves?

        That sounds as bad as relying on undefined behaviour in C.

        • Laremere 2 hours ago

          It's not an optimization. What gets evaluated via the lazy evaluation is well defined. Control flow which has a value defined at comptime will only evaluate the path taken. In the op example, the block is evaluated twice, once for each enum value, and the inner switch is followed at comptime so only one prong is evaluated.

        • 9029 an hour ago

          Nope, this is not relying on optimization, it's just how compile time evaluation works. The language guarantees "folding" here regardless of optimization level in use. The inline keyword used in the original post is not an optimization hint, it does a specific thing. It forces the switch prong to be evaluated for all possible values. This makes the value comptime, which makes it possible to have a comptime unreachable prong when switching on it.

          There are similarities here to C++ if constexpr and static_assert, if those are familiar to you.

        • anonymoushn 2 hours ago

          Well, for example you may have some functions which accept types and return types, which are not compatible with some input types, and indicate their incompatibility by raising an error so that compilation fails. If the program actually does not pass some type to such a function that leads to this sort of error, it would seem like a bug for the compiler to choose to evaluate that function with that argument anyway, in the same way that it would be a bug if I had said "template" throughout this comment. And it is not generally regarded as a deficiency in C++ that if the compiler suddenly chose to instantiate every template with every value or type, some of the resulting instantiations would not compile.

          • dwattttt 2 hours ago

            To take an extreme example, what if I asserted the Riemann hypothesis in comptime? It's relying on comptime execution to act as a proof checker.

            Which is fine for small inputs and uses, but it's not something that would scale well.

dlahoda 2 hours ago

fn main() {

    if false {

        const _:() =  panic!();

    }
}

Fails to compile in Rust.

  • Sharlin 2 hours ago

    Sure, because it's compile-time code inside a (semantically) run-time check. In recent Rust versions you can do

        fn main() {
            const {
                if false {
                    let _:() = panic!();
                }
            }
        }
    
    which compiles as expected. (Note that if the binding were `const` instead of `let`, it'd still have failed to compile, because the semantics don't change.)
  • Ygg2 2 hours ago

    Why would it? If I recall correctly, const and static stuff basically gets inlined at the beginning of the program.