Live data from Hacker News

Things Zig comptime won't do

matklad.github.io

221–230 of 252 posts

Re: Things Zig comptime won't do

#221

Earlier quoted context omitted.

Here 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…

D doesn't have a macro system, either, so I don't understand what you mean.

IIUC, 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.

Re: Things Zig comptime won't do

#222

Earlier quoted context omitted.

> 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.

When 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…

> 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.

Picking a set of well motivated and orthogonal features that combine well in flexible ways is definitely enough to be revolutionary if that combination permits expressive programming in ways that used to be unwieldy, error-prone or redundant, eg. "redundant" in the sense that you have multiple ways of expressing the same thing in overlapping but possibly incompatible ways. It doesn't follow that every language must be revolutionary just because they pick features too, there are conditions to qualify.

For systems programming, I think Zig is revolutionary. I don't think any other language matches Zig's cross-compilation, cross-platform and metaprogramming story in such a simple package. And I don't even use Zig, I'm just a programming language theory enthusiast.

> I agree with Walter: Zig isn't doing anything novel.

"Novel" is relative. Anyone familiar with MetaOCaml wouldn't have seen Zig as particularly novel in a theoretical sense, as comptime is effectively a restricted multistage language. It's definitely revolutionary for an industry language though. I think D has too much baggage to qualify, even if many Zig expressions have translations into D.

Re: Things Zig comptime won't do

#223
post #209
post #203

Earlier quoted context omitted.

Maybe you can insist that these are two features (although I disagree), but calling one of them templates really misses the mark. That's because, at least in C++, templates have their own template-level language (of "metafunctions"), whereas that's not the case in Zig. E.g. that C++'s `std::enable_if` is just the regular `if` in Zig makes all the difference (and also shows why there may not really be two features her…

Agreed. Zig's approach re-uses the existing machinery of the language far more than C++ templates do. Another example of this is that Zig has almost no restrictions on what kinds of values can be `comptime` parameters. In C++, "non-type template parameters" are restricted to a small subset of types (integers, enums, and a few others). Rust's "const generics" are even more restrictive: only integers for now. In Zig I…

> Zig has almost no restrictions on what kinds of values can be `comptime` parameters.

Neither does D. The main restriction is the CTFE needs to be pure. I.e. you cannot call the operating system in CTFE (this is a deliberate restriction, mainly to avoid clever malware).

CTFE isn't "special" in D, either. CTFE is triggered for any instance of a "constant expression" in the grammar, and doesn't require a keyword.

Re: Things Zig comptime won't do

#224

Earlier quoted context omitted.

D doesn't have a macro system, either, so I don't understand what you mean.

IIUC, 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…

> 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".

Re: Things Zig comptime won't do

#225
post #207

Earlier quoted context omitted.

But Zig's comptime only approximates the features you mentioned; it doesn't fully implement them. Which is what the original article is saying. To use your analogy, using a touchscreen to eliminate a keyboard isn't very impressive if your touchscreen keyboard is missing keys. If you say that incomplete implementations count, then I could argue that the C preprocessor subsumes generics/templates, interfaces/typeclasse…

> But Zig's comptime only approximates the features you mentioned; it doesn't fully implement them That's like saying that a touchscreen device without a keyboard only approximates a keyboard but doesn't fully implement one. The important thing is that the feature performs the duty of those other features. > If you say that incomplete implementations count, then I could argue that the C preprocessor subsumes generics…

> The important thing is that the feature performs the duty of those other features.

Zig's comptime doesn't do everything that Rust (or Java, or C#, or Swift, etc.) generics do, and I know you know this given your background in type theory. Zig doesn't allow for the inference and type-directed method resolution that Rust or the above languages do, because the "generics" that you create using Zig comptime aren't typechecked until they're instantiated. You can improve the error messages using "comptime if" or whatever Zig calls it (at the cost of a lot of ergonomics), but the compiler still can't reliably typecheck the bodies of generic functions before the compiler does the comptime evaluation.

Now I imagine you think that this feature doesn't matter, or at least doesn't matter enough to be worth the complexity it adds to the compiler. (I disagree, of course, because I find reliable IDE autocomplete and inline error messages to be enormously useful when writing generic Rust functions.) But that's the entire point: Zig comptime is not performing the duty of generics; it's approximating generics in a way that offers a tradeoff.

When I first looked at Zig comptime, it didn't evoke the "magic of Lisp" at all in me (and I do share an appreciation of simplicity in programming languages, though I feel like Scheme offers more of that than Lisp). Rather, my reaction was "oh, this is basically just what D does", having played with D a decent amount in years prior. Nothing I've seen in the intervening years has changed that impression. Zig's metaprogramming features are a spin on metaprogramming facilities that D thoroughly explored over a decade before Zig came on the scene.

Edit: Here's an experiment. Start with D and start removing features: GC, the class system, exceptions, etc. etc. Do you get to something that's more or less Zig modulo syntax? From what I can tell, you do. That's what I mean by "not revolutionary".

Re: Things Zig comptime won't do

#226

Earlier quoted context omitted.

Comptime is often pushed as being something extraordinarily special, when it's not. Many other languages have similar. Jai, Vlang, Dlang, etc... What could be argued, is if Zig's version of it is comparatively better, but that is a very difficult argument to make. Not only in terms of how different languages are used, but something like an overall comparison of features looks to be needed in order to make any kind of…

You didn't read the article because that's the argument being made (whether you think these points have merit) : > My understanding is that Jai, for example, doesn’t do this, and runs comptime code on the host. > Many powerful compile-time meta programming systems work by allowing you to inject arbitrary strings into compilation, sort of like #include whose argument is a shell-script that generates the text to includ…

The comment made by me, is a reply to another reader, not of the article directly. The push back was on the nature of their comment.

> the uniqueness of Zig's comptime... > You can like it or not, but it is very interesting and very novel...

While true, such features in Zig can be interesting, they are not particularly novel (as other highly knowledgeable readers have pointed out). Zig's comptime is often marketed or hyped as being special, while overlooking that other languages often do similar, but have their own perspectives and reasoning on how metaprogramming and those type of features fit into their language. Not to mention, metaprogramming has its downsides too. It's not all roses.

The article does seek to make comparisons with other languages, but arguably out of context, as to what those languages are trying to achieve with their feature sets. Comptime should not be looked at in a bubble, but as part of the language as a whole.

A language creator with an interesting take on metaprogramming in general, is Ginger Bill (of Odin). Who often has enthusiasts attempt to pressure him into making more extensive use of it in his language, but he pushes back because of various problems it can cause, and has argued he often comes up with optimal solutions without it. There are different sides to the story, in regards to usage and goals, relative to the various languages being considered.

Re: Things Zig comptime won't do

#227
post #207

Earlier quoted context omitted.

> But Zig's comptime only approximates the features you mentioned; it doesn't fully implement them That's like saying that a touchscreen device without a keyboard only approximates a keyboard but doesn't fully implement one. The important thing is that the feature performs the duty of those other features. > If you say that incomplete implementations count, then I could argue that the C preprocessor subsumes generics…

> The important thing is that the feature performs the duty of those other features. Zig's comptime doesn't do everything that Rust (or Java, or C#, or Swift, etc.) generics do, and I know you know this given your background in type theory. Zig doesn't allow for the inference and type-directed method resolution that Rust or the above languages do, because the "generics" that you create using Zig comptime aren't typec…

> Zig doesn't allow for the inference and type-directed method resolution that Rust or the above languages do

Well, but Zig also doesn't allow for overloads and always opts for explicitness regardless of comptime, so I would say that's consonant with the rest of the design.

> Now I imagine you think that this feature doesn't matter, or at least doesn't matter enough to be worth the complexity it adds to the compiler.

I don't care too much about the complexity of the compiler (except in how compilation times are affected), but I do care about the complexity of the language. And yes, there are obviously tradeoffs here, but they're not the same tradeoffs as C++ templates and I think it's refreshing. I can't yet tell how "good" the tradeoff is.

> Here's an experiment. Start with D and start removing features: GC, the class system, exceptions, etc. etc. Do you get to something that's more or less Zig modulo syntax?

I don't know D well enough to tell. I'd probably start by looking at how D would do this [1]: https://ziglang.org/documentation/master/#Case-Study-print-i...

For instance, the notion of a comptime variable (for which I couldn't find an analogue in D) is essential to the point that the "metalanguage" and the object language are pretty much the same language.

Interestingly, in Zig, the "metalanguage" is closer to being a superset of the object language whereas in other languages with compile-time phases, the metalanguage, if not distinct, is closer to being a subset. I think Terra is an interesting point of comparison, because there, while distinct, the metalanguage is also very rich.

[1] which, to me, gives the "magical Lisp feeling" except without macros.

Re: Things Zig comptime won't do

#228
post #203

Earlier quoted context omitted.

I think another way to put it is that the fact that Zig reuses the keyword "comptime" to denote type-level parameters and to denote compile-time evaluation doesn't mean that there's only one feature. There are still two features (templates and CTFE), just two features that happen to use the same keyword.

Maybe you can insist that these are two features (although I disagree), but calling one of them templates really misses the mark. That's because, at least in C++, templates have their own template-level language (of "metafunctions"), whereas that's not the case in Zig. E.g. that C++'s `std::enable_if` is just the regular `if` in Zig makes all the difference (and also shows why there may not really be two features her…

std::enable_if is not the correct comparison, I think you mean "if constexpr"

enable_if is mostly deprecated, and was used for overloading not branching, you can use concepts now instead

Re: Things Zig comptime won't do

#229

Earlier quoted context omitted.

> 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.

When 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…

> 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.

You can say that about the design of any product. Yet, once in a while, we get revolutionary designs (even if every feature in isolation is not completely novel) when the choice of what to include and what to leave out is radically different from other products in the same category in a way that creates a unique experience.

Re: Things Zig comptime won't do

#230
post #55

zig's comptime has some (objectively: debatable? subjectively: definite) shortcomings that the zig community then overcomes with zig build to generate code-as-strings to be lateron @imported and compiled. Practically, "zig build"-time-eval. As such there's another 'comptime' stage with more freedom, unlimited run-time (no @setEvalBranchQuota), can do IO (DB schema, network lookups, etc.) but you lose the freedom to g…

> The zig community bewilders me at times with their love for lashing themselves. The sort of discussions which new sort of self-harm they'd love to enforce on everybody is borderline disturbing. Personally, I find the idea that a compiler might be able to reach outside itself completely terrifying (Access the network or a database? Are you nuts?). That should be 100% the job of a build system. Now, you can certainly…

> That should be 100% the job of a build system.

What is the primary difference between build system and compiler in your mind? Why not have the compiler know how to build things, and so compile-time codegen you want to put in the build system, happens during compilation?

Post reply on HN