5 ms·
If I understand TFA correctly, the author claims that D’s approach is actually different: https://matklad.github.io/2025/04/19/things-zig-comptime-wont-do.html#
by msteffen 1y ago
If I understand TFA correctly, the author claims that D’s approach is actually different: https://matklad.github.io/2025/04/19/things-zig-comptime-wont-do.html#:~:text=For%20example%2C%20D%20mixins%20work%20that%20way https://matklad.github.io/2025/04/19/things-zig-comptime-won...
“In contrast, there’s absolutely no facility for dynamic source code generation in Zig. You just can’t do that, the feature isn’t! [sic]
Zig has a completely different feature, partial evaluation/specialization, which, none the less, is enough to cover most of use-cases for dynamic code generation.”
- WalterBright 1y agoThe partial evaluation/specialization is accomplished in D using a template. The example from the link: fn f(comptime x: u32, y: u32) u32 { if (x == 0) return y + 1; if (x == 1) return y * 2; return y; } and in D: uint f(uint x)(uint y) { if (x == 0) return y + 1; if (x == 1) return y * 2; return y; } The two parameter lists make it a function template, the first set of parameters are the template parameters, which are compile time. The second set are the runtime parameters. The compile time parameters can also be types, and aliased symbols.
- msteffen 1y agoHere is, I think, an interesting example of the kind of thing TFA is talking about. In case you’re not already familiar, there’s an issue that game devs sometimes struggle with, where, in C/C++, an array of structs (AoS) has a nice syntactic representation in the language and is easy to work with/avoid leaks, but a struct of arrays (SoA) has a more compact layout in memory and better performance. Zig has a library to that allows you to have an AoS that is laid out in memory like a SoA: https://zig.news/kristoff/struct-of-arrays-soa-in-zig-easy-in-userland-40m0 https://zig.news/kristoff/struct-of-arrays-soa-in-zig-easy-i... . If you read the implementation (https://github.com/ziglang/zig/blob/master/lib/std/multi_array_list.zig https://github.com/ziglang/zig/blob/master/lib/std/multi_arr...) the SoA is an elaborately specialized type, parameterized on a struct type that it introspects at compile time. It’s neat because one might reach for macros for this sort of the thing (and I’d expect the implementation to be quite complex, if it’s even possible) but the details of Zig’s comptime—you can inspect the fields of the type parameter struct, and the SoA can be highly flexible about its own fields—mean that you don’t need a macro system, and the Zig implementation is actually simpler than a macro approach probably would be.
- WalterBright 1y agoD doesn't have a macro system, either, so I don't understand what you mean.
- msteffen 1y agoIIUC, it does have code generation—the ability to generate strings at compile-time and feed them back into the compiler. The argument that the author of TFA is making is that Zig’s comptime is a very limited feature (which, they argue, is good. It restricts users from introducing architecture dependencies/cross-compilation bugs, is more amenable to optimization, etc), and yet it allows users to do most of the things that more general alternatives (such as code generation or a macro system) are often used for. In other words, while Zig of course didn’t invent compile-time functions (see lisp macros), it is notable and useful from a PL perspective if Zig users are doing things that seem to require macros or code generation without actually having those features. D users, in contrast, do have code generation. Or, alternatively, while many languages support metaprogramming of some kind, Zig’s metaprogramming language is at a unique maxima of safety (which macros and code generation lack) and utility (which e.g. Java/Go runtime reflection, which couldn’t do the AoS/SoA thing, lack) Edit Ok, I think Zig comptime expressions are just like D templates, like you said. The syntax is nicer than C++ templates. Zig’s “No host leakage” (to guarantee cross-compile-ability) looks like the one possibly substantively different thing.
- WalterBright 1y ago> Zig’s “No host leakage” (to guarantee cross-compile-ability) looks like the one possibly substantively different thing. That is a good idea, but could be problematic if one relies on size_t, which changes in size from 32 to 64 bit. D's CTFE adds checks for undefined behavior, such as shifting by more bits than are in the type being shifted. These checks are not done at runtime for performance reasons. D's CTFE also does not allow calling the operating system, and only works on functions that are "pure".
- pron 1y ago
- naasking 1y agoUsing a different type vs. a different syntax can be an important usability consideration, particularly since D also has templates and other features, where Zig provides only the comptime type for all of them. Homogeneity can also be a nice usability win, though there are downsides as well.
- WalterBright 1y agoZig's use of comptime in a function argument makes it a template :-/ I bet if you use such a function with different comptime arguments, compile it, and dump the assembler you'll see that function appearing multiple times, each with somewhat different code generated for it.
- naasking 1y ago> Zig's use of comptime in a function argument makes it a template :-/ That you can draw an isomorphism between two things does not mean they are ergonomically identical.
- pcwalton 1y agoWhen we're responding to quite valid points about other languages having essentially the same features as Zig with subjective claims about ergonomics, the idea that Zig comptime is "revolutionary" is looking awfully flimsy. I agree with Walter: Zig isn't doing anything novel. Picking some features while leaving others out is something that every language does; if doing that is enough to make a language "revolutionary", then every language is revolutionary. The reality is a lot simpler and more boring: for Zig enthusiasts, the set of features that Zig has appeals to them. Just like enthusiasts of every programming language.
- pron 1y agoI'm sorry, but not being able to see that a design that uses a touchscreen to eliminate the keyboard is novel despite the touchscreen itself having been used elsewhere alongside a keyboard, shows a misunderstanding of what design is. Show me the language that used a general purpose compile-time mechanisms to avoid specialised features such as generics/templates, interfaces/typeclasses, macros, and conditional compilation before Zig, then I'll say that language was revolutionary. I also find it hard to believe that you can't see how replacing all these features with a single one (that isn't AST macros) is novel. I'm not saying you have to think it's a good idea -- that's a matter of personal taste (at least until we can collect more objective data) -- but it's clearly novel. I don't know all the languages in the world and it's possible there was a language that did that before Zig, but none of the languages mentioned here did. Of course, it's possible that no other language did that because it's stupid, but that doesn't mean it's not novel (especially as the outcome does not appear stupid on the face of it).
- baazaa 1y agothat's a comically archaic way of using the verb 'to be', not a grammatical error. you see it in phrases like "to be or not to be", or "i think, therefore i am". "the feature isn't" just means it doesn't exist.
- CRConrad 1y agoDamn, beat me by half a day.
- sixthDot 1y agoSure, CTFE can be used to generate strings, then later "mixed-in" as source code, but also can be used to execute normal functions and then the result can be stored in a compile-time constant (in D that's the `enum` storage class), for example generating an array using a function literal called at compile-time: enum arr = { return iota(5).map!(i => i * 10).array; }(); static assert(arr == [0,10,20,30,40]);
- CRConrad 1y ago> the feature isn’t! [sic] To be, or not to be... The feature is not. (IOW, English may not be the author's native language. I'm fairly sure it means "The feature doesn't exist".)