1. Tooling (as an extension to the mentioned IDE support point). Zig and Rust are both praised for their tooling and I think rightfully so. The C/C++ interop story and the cross-compiling story in Zig are great. From the standpoint of a working practitioner though I think Rust is way ahead. Not surprising given that Zig is much younger, but something to keep in mind.
2. Compile Time Stuff: Here Zig is praised and Rust not so much. I think this is undeserved. Rust has much higher aspirations for their compile time features, namely that outcome must be identical regardless when the code runs. This is a very useful property but makes the task much harder and fundamentally incomparable with Zig comptime.
Yes. For example in Rust it took a long time for floating point operations to be available at compile time and even now only a subset is. The reason is that a lot of energy and thought went into the issue of producing identical output (and what identical precisely means ) even when compilation is on a different processor than where the target runs.
As far as I know this is not a concern for Zig comptime.
there has been a ton of work on making comptime a pure and deterministic execution environment. I do not expect that work to stop. I don't know where you are getting the idea that it is not an important design consideration for the language.
to expand, if two different host platforms cross compiling to the same target platform have different results, I am almost certain that would be considered a compiler bug.
if you're pointing out that a runtime operation and a compile time operation might not agree, I'd be more interested in understanding when that would ever have any meaningful impact on anything. given the compilation is supposed to be deterministic, the difference can easily be addressed by comptime branching on target architecture in the rare case that it matters for your program.
I think there's some misconceptions floating around here regarding both Rust and Zig's const-evaluation philosophies.
Rust is concerned about memory-safety, yes, but the only strict requirement for memory-safety when it comes to const-evaluation is as follows: "The only guarantee the type system needs is that evaluating `some_crate::SOME_CONST` will produce consistent results if evaluation is repeated in different compilation units" ( <a href="https://rust-lang.github.io/rfcs/3514-float-semantics.html" rel="nofollow">https://rust-lang.github.io/rfcs/3514-float-semantics.html ).
Beyond that, from a philosophical standpoint, Rust takes great pains to ensure that const functions produce identical results regardless of whether or not those functions are called at compile-time or at runtime. Rust has adopted this stance because it wants to reserve the right to opportunistically evaluate const-capable functions at compile time, as a performance optimization, even if the user has not explicitly asked for it (for that matter, Rust also does its best to const-evaluate non-const functions when it can). Because of this, Rust's assumption is that users would be annoyed if their program's visible behavior depends on whether or not the optimizer has exercised its discretion to evaluate a specific function at compile-time.
However, this is only a guideline, not a strict guarantee. There is one exception to the above rule: "when a floating-point operation produces a NaN result, the resulting NaN bit pattern is some deterministic function of the operation’s inputs that satisfies the constraints placed on run-time floating point semantics. However, the exact function is not specified, and it is allowed to change across targets and Rust versions, and even with compiler flags. In particular, there is no guarantee that the choice made in const evaluation is consistent with the choice made at runtime."
In other words, calling the `.to_bits()` function on a floating-point value that happens to be NaN is allowed to produce a different result at runtime than it does at compile-time (note that all compile-time evaluations are guaranteed to always produce the same result for a given toolchain version for a given target, as required above).
This exception is made because otherwise otherwise it would be basically impossible to support floating-point math at all, thanks to the way various platforms have implemented their floating-point functions in practice.
In contrast, Zig doesn't have such a philosophical compunction against a function's result being determined by whether or not it's being evaluated at compile-time, as shown by the existence of the `@inComptime` builtin. But Zig does still broadly attempt to make comptime deterministic, including going so far as to forbid I/O, though I don't see where any specific guarantees are documented in the Zig reference.
weinzierl · · focus · HN ↗
1. Tooling (as an extension to the mentioned IDE support point). Zig and Rust are both praised for their tooling and I think rightfully so. The C/C++ interop story and the cross-compiling story in Zig are great. From the standpoint of a working practitioner though I think Rust is way ahead. Not surprising given that Zig is much younger, but something to keep in mind.
2. Compile Time Stuff: Here Zig is praised and Rust not so much. I think this is undeserved. Rust has much higher aspirations for their compile time features, namely that outcome must be identical regardless when the code runs. This is a very useful property but makes the task much harder and fundamentally incomparable with Zig comptime.
chaz72 · · focus · HN ↗
weinzierl · · focus · HN ↗
As far as I know this is not a concern for Zig comptime.
rvrb · · focus · HN ↗
to expand, if two different host platforms cross compiling to the same target platform have different results, I am almost certain that would be considered a compiler bug.
if you're pointing out that a runtime operation and a compile time operation might not agree, I'd be more interested in understanding when that would ever have any meaningful impact on anything. given the compilation is supposed to be deterministic, the difference can easily be addressed by comptime branching on target architecture in the rare case that it matters for your program.
weinzierl · · focus · HN ↗
It's something Rust guarantees (without me having to take care of it e.g. by manually branching) and Zig does not.
rvrb · · focus · HN ↗
I am genuinely interested in a place that this matters for a program, or any practical consequence this has for an end user of the language.
no idea why your response was flagged originally.
kibwen · · focus · HN ↗
Rust is concerned about memory-safety, yes, but the only strict requirement for memory-safety when it comes to const-evaluation is as follows: "The only guarantee the type system needs is that evaluating `some_crate::SOME_CONST` will produce consistent results if evaluation is repeated in different compilation units" ( <a href="https://rust-lang.github.io/rfcs/3514-float-semantics.html" rel="nofollow">https://rust-lang.github.io/rfcs/3514-float-semantics.html ).
Beyond that, from a philosophical standpoint, Rust takes great pains to ensure that const functions produce identical results regardless of whether or not those functions are called at compile-time or at runtime. Rust has adopted this stance because it wants to reserve the right to opportunistically evaluate const-capable functions at compile time, as a performance optimization, even if the user has not explicitly asked for it (for that matter, Rust also does its best to const-evaluate non-const functions when it can). Because of this, Rust's assumption is that users would be annoyed if their program's visible behavior depends on whether or not the optimizer has exercised its discretion to evaluate a specific function at compile-time.
However, this is only a guideline, not a strict guarantee. There is one exception to the above rule: "when a floating-point operation produces a NaN result, the resulting NaN bit pattern is some deterministic function of the operation’s inputs that satisfies the constraints placed on run-time floating point semantics. However, the exact function is not specified, and it is allowed to change across targets and Rust versions, and even with compiler flags. In particular, there is no guarantee that the choice made in const evaluation is consistent with the choice made at runtime."
In other words, calling the `.to_bits()` function on a floating-point value that happens to be NaN is allowed to produce a different result at runtime than it does at compile-time (note that all compile-time evaluations are guaranteed to always produce the same result for a given toolchain version for a given target, as required above).
This exception is made because otherwise otherwise it would be basically impossible to support floating-point math at all, thanks to the way various platforms have implemented their floating-point functions in practice.
In contrast, Zig doesn't have such a philosophical compunction against a function's result being determined by whether or not it's being evaluated at compile-time, as shown by the existence of the `@inComptime` builtin. But Zig does still broadly attempt to make comptime deterministic, including going so far as to forbid I/O, though I don't see where any specific guarantees are documented in the Zig reference.