5 ms·
Why is 90% enough?
by wocram 11mo ago
Why is 90% enough?
- CitrusFruits 11mo agoI think the idea is that perfect is the enemy of good here and that getting from 90% to 100% involves tradeoffs that aren't actually worth it from a language ergonomics point of view.
- bsder 11mo agoWhat are you trading off to get from 90% to 100%? How about compile speed? Are you willing to wait an extra second to get 100%? How about 10 seconds? A minute? 10 Minutes? An hour? Rust is notoriously slow at compiling and people have been banging on it for a while. At some point, you have to accept that the language, itself, has properties that make compilation slow.
- kristianp 11mo agoRust packages tend to have large dependency graphs which doesn't help the compile times. I've read the serde is a bit of a hog in that respect, for example. The rust philosophy is for a large language and large library too.
- matesz 11mo agoI highly recommend checking out makepad [1] - they have +100k of rust code and the compile time is around 10-15 seconds on commodity hardware. However they are obsessed about performance. They reason for such speedy compile times, like you say, is that makepad has almost no external dependencies. [1] https://github.com/makepad/makepad/ https://github.com/makepad/makepad/
- scuff3d 11mo agoI don't think you understand what he saying. Rust is 100% memory safe in specific places yes, but much less so when you have to dip into unsafe Rust. Unsafe memory access will always exist, you can't do anything about it. If you need to interact with the underlying system it's just something you have to deal with it. Zig on the other hand isn't 100% safe in any one part, but it's 90% safe in nearly all parts. Zig recognizes the outside world exists, and makes it easy to write safe correct code given that reality. Time will tell, but on average I suspect Zig and Rust will produce equally safe and correct software. The further away you get from the hardware the bigger Rust's advantage is, the closer you get to the hardware Zig has the edge.
- neckbeards 11mo agoHow is Zig considered “90% safe”? It relies on manual memory management, its simple type system provides limited compile-time guarantees and it lacks a mature concurrency model (making safe parallelism difficult). Given these gaps, I struggle to see how Zig achieves a consistently high level of safety. It seems no safer than using AddressSanitizer at best?
- scuff3d 11mo agoZig makes a lot of small choices that pile up to push you towards safety/correctness in your code. No hidden allocations is a big one. If something allocates you have to explicitly give it an allocator. This makes tracking allocations much simpler. Combined with the test allocator you can also detect memory leaks. Allocators also simplify memory management patterns. For example, it's trivially ease to use an arena. Then all your little allocations can be freed all at once, eliminating the need to track each individual allocation/free. The defer keyword allows you to place the free call near the allocation (same with other resources that require closing). This isn't always possible of course, but it is a lot of the time and makes it easier to track. Bounds checking is another big one. While loops/for loops with capture groups means you'll basically always see Zig programs iterating through arrays/slices in a manner that ensures you can't go out of bounds. In terms of general correctness you have explicit nullability. If something can be null you have to mark it as such directly in the type. Then when accessing it you have to unwrap it and deal with the null case. Same for errors. If something can return an error it's indicated in the return type. The error has to be unwrapped and then thanks to tagged unions you have to deal with all the different possible cases. There are language conviences like the try keyword that let you side step some of the explicit handling, but even those are easy to track. And you know you're doing something that might bite you. All of that adds up with a dozen other design choices to produce a language that makes it a lot easier to produce correct code. Edit: In terms of concurrency I have to give you that one. The language is still pre 1.0 so we'll have to see what happens.
- neckbeards 11mo agoThanks for the response. I look forward to seeing how the type system evolves. - No hidden allocations: Other languages already provide abstractions for this. Are hidden allocations really a significant issue in modern systems languages, even when managing memory manually? This concern is distinct from memory leaks or general memory safety problems. - Allocators: It's easy to use an arena in C++ or C. - defer keyword: Similar constructs have existed in other languages and even as a GNU C extension for many years. - Bounds checking: Not an issue in Rust. The real source of risk has always been raw pointer manipulation, which Zig doesn't (cannot?) solve. How is it better than address sanitizer? Rust solves this at the language level. - Nullability: GCC has long supported non-null attributes and unused-result annotations and Clang provides _Nullable. C++ goes further with type-level guarantees via std::optional, gsl::not_null and related abstractions. - Errors: Zig’s approach is clean but equivalent mechanisms exist in C++ (std::expected) and Rust (Result and error types). It’s mainly cumbersome in plain C. All of these are useful quality-of-life improvements but they don’t address my problems in systems programming (such as efficient and composable data structures, data movement, scalable concurrency, safe memory management ...and boiler-plate, lots of boiler-plate). These problems are easier to solve with a type system that allows me to make strong correctness guarantees and extend those guarantees. Lastly, I’m unsure that any potential boilerplate reduction would be significant if implemented in Zig.