4 ms·
Focus on the compile error story. In particular, the design should avoid anything that leads to post-monomorphization errors. This is the single biggest mistak
by j-pb 3y ago
Focus on the compile error story. In particular, the design should avoid anything that leads to post-monomorphization errors.
This is the single biggest mistake of Rust imho. I don't care in which compiler pass an error occurs as long as it happens at compile time.
Rust has this anyways, you can already create types that fail after monomorphization, so you don't get any of the touted advantages anyways. You might as well bite the bullet accept that the people who say “You guys are dumb, just copy Zig’s type system” have a point, and shed some of the ivory tower dogma in exchange for a better language. It's completely fine for monomorphization to fail, and it allows you to create much more powerfull types.
Rust is already incredibly complex, and most of that complexity comes from dozens of different systems that share few concepts all with their own syntax (modules, macros, traits, e.t.c.), so adding yet another syntax for static loops begs the question if some of this can't be unified.
Zig is a seriously flawed language, but comptime is the right abstraction for metaprogramming in an imperative language.
- ngrilly 3y agoA bit off-topic, but since you mentioned it, why is Zig a "seriously flawed language"?
- j-pb 3y agoPriorities. The team is too focused on global maxima, speed and reinventing compiler design at the cost of a reference implementation that's fundamentally broken, and too complex to fix. This results in miscompilations, broken buildins, features added that are then ripped out again. I think fast iterations and experimental stuff are ok if you have a stable core. I.e. I don't mind if zig decides to change its for loop syntax after 5 years, so long as there is a simpler stable construct like `loop { break; }` that people that use the language in production and library maintainers can use. You need a certain critical mass for a language to be self sustaining, and that requires people to actually use your stuff, which in turn requires at least some stability guarantees for some subset of the language. Zig's response to that is "I'm just my inventors toy yet, but it will be grand when version 1.0 hits in 10-50 years." The fact that they now want to replace LLVM with their own backend makes me think that even 50 years would be optimistic.
- rastignack 3y agoI think the plan is to avoid linking with llvm, not getting rid of llvm altogether. To be fair go has never used llvm and was delivered in less that 50 years.
- j-pb 3y ago> To be fair go has never used llvm and was delivered in less that 50 years. And if Zig was a google project instead of a 3 person show, I'd be far more inclined to believe that they can pull this off. But as previously said, the current style of development makes it hard to attract contributors and more importantly funding.
- DannyBee 3y agoGo did not have the goal of the best possible performance, it was targeting good performance with amazing compile times. It still targets this. It was also developed by some of the most productive geniuses in the world (disclaimer: the go team used to report up through me) Getting to 70 percent of llvm will be relatively easy for zig and like all others, they will congratulate themselves and pretend it validates their choice. They will then discover the other 30 percent happens 0.1% at a time, because there are no silver bullets. This will take them 10+ years because it always does.
- TUSF 3y agoYeah, LLVM is here to stay for Zig. The plan is to have a custom backend for fast Debug builds for use during development, while emitting LLVM bitcode for release builds that can then be fed to LLVM. Not linking to LLVM would also make the barrier to entry on contributing to Zig itself lower, because now you can just compile Zig with Zig, and not worry about other dependencies.
- PoignardAzur 3y ago> You might as well bite the bullet accept that the people who say “You guys are dumb, just copy Zig’s type system” have a point, and shed some of the ivory tower dogma in exchange for a better language. The fact that you call it "dogma" (and your other comments about Zig) suggests that you aren't going to be very open to changing your mind on this. But as far as "the touted advantages" go, I've experienced them firsthand. Being able to write generic code and know that if the code compiles in your library, it will compile for people who depend on it, is a pretty nice workflow. Being able to change that generic code and still be confident it will still compile for downstream users who download the new version is pretty nice too. Being able to download some random dependency full of generic code, and to instantiate that code without having to dread reading mile-long call stacks that end with "foo.bar is not implemented in this function you didn't write" is pretty nice too. (And yes, post-monomorphization errors can still happen in theory; I've never seen one happen in practice, certainly not with the frequency I saw the mile-long call stacks in C++.) Those aren't some aesthetic details that language designers cling to out of some perfectionist desire to keep the language theoretically pure. It's part of what makes pulling dependencies especially painless in Rust.
- gpderetta 3y agoI don't want to discount the usefulness of definition-time type checking of generics, but (compile time) tests against archetypes are an obvious way to make sure that your generic code instantiates correctly.
- j-pb 3y agoThere a million ways your code can break downstream dependencies, generic code is just one of them. Breaking stuff when you change things is just in the nature of it, which is why not changing APIs is so important. But I'd rather have the compiler errors you describe as something my IDE can jump to, than to spend hours poking around in opaque macro black boxes, because half of every library is a huge chunk of copy pasted code and macro magic to get around the type system. Rust as is, is a de Bruijn criteria fulfilling proof language, with the macro system ending up as the meta language.
- CodesInChaos 3y agoCurrently the compiler can choose to omit monomorphization, if the code is unused. If monomorphization can fail, the compiler needs to compute some unused monomorphizations, just to ensure they don't raise an error. This could hurt compile times. Otherwise you get compilation failures that depend on the exact way the compiler decides which monomorphizations are used. Plus otherwise semver compatible changes in a dependency can surface latent monomorphization failures, breaking the build. However I do overall agree with you, that rust needs to accept post-monomorphization errors. I see no way to get usable const-generics otherwise.
- j-pb 3y agoYeah, It's not that I don't see the advantages. I wish that there was a way to get our cake and eat it too. Maybe we can dependently typed eat our way through to the other end, where while we do have monomorphization errors, having constraints on generic types feel natural and ergonomic, much more like in a system like Lean. I think what it boils down to at the end is where you want your pain to be, pains from constantly hitting limitations and providing an escape hatch like macros, or pains from having a system that is too powerful and all the chaos that brings. I'd rather reign in the chaos, after all we also choose to be Turing-complete, and not always terminating like Coq, but mmv.