5 ms·
I see this line repeated a lot, especially in Zig spaces, but it doesn't really make sense to me. Rust is an excellent replacement for C, even though it has mor
by slondr 3y ago
I see this line repeated a lot, especially in Zig spaces, but it doesn't really make sense to me. Rust is an excellent replacement for C, even though it has more features. What makes C the language of choice for so many applications is not its lack of features.
- drowsspa 3y agoIt's been a long time since I've programmed in C, but AFAIK the major pain points were and continue to be the build system and the preprocessor (or consequences of those). Zig does seem to fix in a pretty simple way
- mananaysiempre 3y ago> I see [Rust : Zig :: C++ : C] repeated a lot, especially in Zig spaces, but it doesn't really make sense to me. Rust is an excellent replacement for C, even though it has more features. It’s the feels, not the features :) Rust code feels like C++ code, at least when you’re reading it (I haven’t written any worth talking about). It puts the problem domain in similar terms, it has similar transparency (or lack thereof) regarding what it’s copying or allocating or whatnot, and so on. In that respect (!) they are closer to each other than C is to either—at least vanilla C, not a DSL (“language overhaul mod”?) like GObject. And it makes sense to target the C side of that divide in a new language (though again I lack the experience to say to which degree Zig succeeds in hitting that target).
- pornel 3y agoThe feels are not very accurate. Rust adopted C++-like syntax to look less weird to C++ programmers, but semantically it is quite a different language. It's more like a low-level Ocaml than C++. Notably: • Rust doesn't have inheritance. This makes a lot of basic C++ programming patterns unfit for Rust, and prevents 1:1 translation of C++ to Rust. • Rust's generics may look like C++ templates, but they're not. Rust's macros behave more like C++ templates, and generics are closer to C++ concepts, but neither is a close match. C++ programmers are generally flabbergasted how hard is to make a function that takes any integer type in Rust. • Even though Rust copied C++ moves, and has "RAII", the way these are used in practice ends up different due to having opposite defaults and different guarantees. Rust doesn't have constructors. Its closest equivalent of exceptions is for a different purpose. Rust's types are always movable, don't have meaningful addresses, can't reference own fields. Even C++'s std::string is hopelessly incompatible with Rust. C++ has two string types, because of C legacy. Rust has two (and more) string types to express different modes of ownership. C++ is a complex language, because they keep adding more ways to initialize a variable. Rust has exactly one way. But Rust has many other features, mostly in its type system, to define thread-safety, memory-safety, and memory management in detail that is beyond what C++ can express. So "but they're both big" is glossing over all the reasons why. However, C happens to be almost a clean subset of Rust. You can take a C program and translate it line by line to Rust. It won't be idiomatic, but may be easy to refactor into proper Rust. That's generally not true with C++, which requires rethinking everything from basic idioms and constructs to the overall architecture. This is why Rust struggles with GUI libraries, and the best-supported native toolkit is from C.
- zeroxfe 3y ago> However, C happens to be almost a clean subset of Rust. You can take a C program and translate it line by line to Rust. I can't see how that's possible, unless you litter your code with `unsafe` all over the place. Rust requires a lot of restructuring around ownership and borrowing to get your code to even compile.
- pornel 3y agoI've done it with a few libraries. They usually have defined ownership, but it's specified in the library's manual, not in the code. Even unusual patterns can generally be mapped to Cow or Option or worst case some custom smart pointer with minimal amount of unsafe. But very often merely converting pointers to & vs &mut vs Box as appropriate gets the job done. The most common sin is C libraries taking just a pointer and hoping for the best, instead of pointer+length for buffers (slices). But that's also a "local" problem you can fix by adding an extra argument, generally not a major redesign. Thread-safety tends to be worse to map, because C reasons about safety of function calls, while Rust about sharing of data types. So "it's safe to call foo unless option bar is set to -5" doesn't translate well.
- pjmlp 3y agoRust has traits inheritance.
- pornel 3y agoSibling comment also says "has interface inheritance with pretty much the same syntax", but this is another case where people see the same ASCII char and think it's the same feature, when it's so different. The A:B syntax is not inheritance, but a syntax sugar for 'A where Self:B' bound. The result is these remain separate traits without support for subtyping. dyn trait A:B can't be used where B is required, unless you have access to the concrete type and make a new vtable for B from scratch. There's WIP to fix that, but not here yet. The auto traits that look like subtyping are for built-in marker traits only. Lack of data inheritance is painful. There's no support for fields in traits. Getters/setters are problematic due to borrowing all of self instead of just the field. Traits can't have private or protected methods. Traits aren't inherent to the types, so you have to import both the type and the trait to use it. It's messy and makes interface docs confusingly fragmented. So Rust really really isn't an OOP language, even though you can put together an awkward-to-use imitation from a few ill-fitting features — but they use the same sigils as OO in C++!
- Mawr 3y agoThat is true in the pragmatic sense, those who only use C for its objective qualities would find Rust a good replacement. However, those who use C because they like the language would not enjoy Rust one bit and would much prefer Zig over it.
- hansvm 3y agoRust limits programs (even when you use unsafe) to those you can prove correct to the copmiler, and it has a habit of taking on more dependencies than necessary for a given task (using syscalls and locks when not required, allocating frequently, ...). It's a nice language, but it made tradeoffs, and a meaningful fraction of C code would be hard to port to or even link from Rust.