5 ms·
Generics, interfaces/traits/concepts, macros, conditional compilation, const functions/constexpr. These are four or five different features in C++ or Rust, some
by pron 2y ago
Generics, interfaces/traits/concepts, macros, conditional compilation, const functions/constexpr. These are four or five different features in C++ or Rust, some of which are quite complex, all expressible as one simple construct: comptime.
- kobebrookskC3 2y agohow does zig express a trait like Send https://doc.rust-lang.org/std/marker/trait.Send.html https://doc.rust-lang.org/std/marker/trait.Send.html which ensures that values can safely be moved to another thread, for example when spawning a thread? https://doc.rust-lang.org/std/thread/fn.spawn.html https://doc.rust-lang.org/std/thread/fn.spawn.html
- throwawaymaths 2y agoif you want that you will need a proof checker or something.
- pcwalton 2y agoSuch as the one Rust provides, and that Zig cannot, due to not being memory safe.
- rc00 2y agoIt sounds like you haven't seen projects like this yet: https://github.com/ityonemo/clr https://github.com/ityonemo/clr They're popping up all over. For some reason, Zig folk want Rust things and Rust folk want Zig things.
- pcwalton 2y agoI have seen projects like that, and they're a prime example of what I mean when I want to see arguments in favor of Zig that rely on what Zig can do now, and not what it could potentially do in the future. Ten years ago, C++ folks were also promising memory safety with the ISO C++ Core Guidelines; you don't hear much about that anymore, because it turns out it can't be done while keeping the resulting language C++ (for example, seanbax's work for C++, which is far more advanced than this project, is really awesome, but is essentially a different language).
- rc00 2y agoAnd what about all the promises of things making it out of Rust Nightly? When it comes to Zig, one crowd says it's too early because it's not 1.0 fast enough. And now, are you saying that the feature development is basically done? What point are you trying to make?
- pcwalton 2y agoThe point I'm making is that I don't believe Zig can be made meaningfully memory safe without breaking compatibility to the extent that memory-safe Zig would effectively be a different language, any more than C can.
- pron 2y agoI tend to agree, but writing code in a memory-safe language is not the goal. The relevant goal on that particular front (and it is not the only goal people have when writing programs) is to maximise the resulting program's correctness within some effort budget and other requirements (such as memory consumption etc.). Using a memory-safe language is one approach toward achieving that goal, but if that safety comes at a cost of added effort, then showing that's the best approach depends on claims that are hard to verify without a lot more empirical data. The only theoretical justification could be that more soundness results in more practical correctness, but if that were the case then there are languages that offer more soundness than Rust. In other words, if Rust is generally superior to Zig because it offers more soundness, then other languages are superior still. Indeed, soundness is not considered the best approach to attaining every property in general because it can be more expensive than other approaches that achieve the desired outcome, and Rust clearly recognises that. Rather, both languages' correctness-related claims rely on them being in some better or worse effort/correctness sweet spot, and that can only be measured empirically for those two specific languages. Crucially, results comparing Rust to C or C++ are not relevant. Zig offers more soundness than C, and even if it offers the same soundness as C++ (and I disagree -- I think it offers more) the language's claim is that its simplicity assists correctness. We can only tell to what extent that is true with more empirical observation; I don't think there can be any good guess made here regarding the size of the effect.
- pcwalton 2y agoHow do you typecheck generics, with type inference, with comptime? Or, more generally, address all the issues raised in [1]. You're saying that comptime can fully replicate all the features that a proper generics system has, which is plainly false. [1]: https://typesanitizer.com/blog/zig-generics.html https://typesanitizer.com/blog/zig-generics.html
- creata 2y agoI don't think pron was saying that Zig has a feature-by-feature match for everything that Rust's generics can do. I think his point is that comptime can handle what the target audience of Zig wants from generics. In that regard, I don't think the criticisms there are that big a deal.
- throwawaymaths 2y ago1. if you wish, you absolutely can check for "extra constraints" on a passed type (or even an anytype parameter) using comptime reflection and the @comptimeError builtin. 2. if you want to restrict the use of a function to comptime (why you would want to is beyond me) it is possible to do with @inComptime builtin. the only tricky bit is that your function could try to call a function inaccessible to you because it's transitively restricted and you'd have a hard time noticing that from the code but it's not possible for that code to be compiled (barring errors by the zig team) so its more of an annoyance than a problem.
- pron 2y agoI would say these are more differences than issues, and that some of those presented as more fundamental ones are actually quite small. Suppose that instead of `fn foo (comptime T : type, ...) { typecheck(T); ...}` Zig introduced just a tiny bit of new syntax to allow you to write something like `fn foo (comptime T : typecheck(T), ...) { ... }` -- i.e. the type constraints would be part of the signature -- would you then say it had generics rather than templates? Personally, I have not made up my mind on whether or not such an addition would be very valuable, but even if it is, it can be done later. That small addition would address most "issues" in the article, which I would say are more about IDE support than anything else. But even without it, what you want to know is known at compile time, and the article admits that the compilation errors are already better than those you get with C++ templates (I would say much better). Now, I'm not saying that Zig's choices always dominate and that all languages would be better off with its approach; far from it. I am saying that it introduces a novel tradeoff that is especially compelling in cases where not only generics but also macros, conditional compilation, and constexprs are otherwise required. In a language like Java these extra features are not required, and so Zig-style comptime would not simplify the language nearly as much. But even in cases where all these features are needed, I don't think everyone would take Zig's choices over C++'s or Rust's, or vice-versa. To those, like me, for whom language complexity is the biggest problem with C++ or Ada (I used Ada in the nineties), Zig is a revolutionary step forward. I don't think any low-level language has ever been this simple while also being this expressive.
- SkiFire13 2y agoComptime can only properly express half of them: - generics: comptime can implement some kind of polymorphism, but not at the type level. In other words it implements a templating system, not a polymorphic type system; - interfaces/traits/concepts: comptime implements none of that, it is plain duck typing, just like "old" C++ templates. In fact C++ introduced concepts to improve its situation with templates, while Zig is still behind on that front! - macros: comptime solves some of the usecases where macros are used, but it cannot produce arbitrary tokens and hence cannot fully replace macros. I do agree that it can neatly replace conditional compilation and const functions/const expr, but let's not make it seem like comptime solves everything in the world.
- throwawaymaths 2y agoin practice aside from interfaces the only thing you can't do at comptime is to generically attach declarations (member functions, consts) to a container type (the best you can do is to do it on a case by case basis). you could probably cobble together an interface system with @comptimeError, but because of the time order of compilation stages, a failed method call will trigger the compiler error before your custom interface code, making it effectively useless for the 90% of cases you care about. if I'm not mistaken in principle a small change to the compiler could amend this situation