Comment by jenadine
3 years ago
The "simplicity" of C is not a good thing. The Brainfuck language is even "simpler" and you can read the spec in 2 minutes. But that does not make it easier, because all the complexity is in the usage.
The abstraction layer that one can build with rust allow the programmer to actually focus of the actual business logic instead of trying to get low level details right.
I think you missed the part about systems programming. When you are programming real hardware, the focus is entirely on low level details. You need to know the commands being sent to the device, the device state, and the ownership of resources by the device (which Rust doesn't solve for) are correct.
The innovation of Rust is the borrow checker, which is primarily of interest to systems programmers. If your primary interest is highly abstracted business logic, there are tools that don't require manual memory management or being pedantic about the different types of strings. You could just use Go, Java, Haskell, Python, etc.
> there are tools that don't require manual memory management or being pedantic about the different types of strings. You could just use Go, Java, Haskell, Python, etc.
1. Rust doesn't force you to do manual memory management. Rust memory management is automatic by default and only if you really, really want to, you can do it manually.
2. Memory is not the only resource. The GCs in languages you listed only solve the memory management problem, but regarding the other types of resources, their ergonomics are often worse than C - you have to remember to close the resources manually and you get virtually no help from the compiler.
3. None of the listed languages address problems related to concurrency, e.g. data races. Ok, Haskell kinda avoids the problem by imposing other restrictions - by not allowing mutation / side effects ;)
4. Rust offers way better tools for building high level abstractions than Go, Python and Java. It has set a very high bar with algebraic data types, pattern matching, traits/generics and macros.
1. Rust does manual memory management. It has some syntactic sugar for it in the form of a compiler-enforced RAII, but that is still manual memory management for all practical purposes. A good distinction to make is whether low-level, memory/ownership details leak into public APIs. This is trivially true for Rust, while is not true of managed languages.
3. Rust only addresses problems related to data races, not as an example. All the other race conditions are still on the table. It is a good thing to have, but I think they are the least problematic, and easiest to solve part of concurrency issues.
4. All of these have been known for like 3 decades. There are plenty of managed languages with these, ML, OCaml, Haskell, Scala. But I think your claim is subjective at best.
13 replies →
> “and the ownership of resources by the device (which Rust doesn't solve for) are correct.”
For embedded software, the underlying code basically reads and writes a bunch of registers. Unsafe memory access with side effects. The benefit of using rust here is that you can easily model these access patterns to make an api that cannot be abused. So the driver reads and writes addresses and the user code operates through the driver with all the benefits of ownership at hand to avoid race conditions and other foot-guns.
So, in this way rust does indeed “solve for” ownership of devices. You can’t have two threads (or interrupt handlers) mutating the same device without satisfying the ownership rules.
>You can’t have two threads (or interrupt handlers) mutating the same device without satisfying the ownership rules.
The trouble with this is that abstract 'devices' don't necessarily map neatly to the underlying hardware. Configuring peripherals on a typical microcontroller typically requires setting flags in a bunch of random registers which don't necessarily have neatly separated responsibilities.
Take PWM as an example. Is there a PWM 'device'? Is there a PWM setting for each port, according to some abstract representation of ports? What about the timer used to generate the PWM output? Does the PWM device own the timer, or does the timer own the PWM device? Any such abstractions cause more problems than they solve. You really just need to think carefully about how you are manipulating the underlying hardware.
1 reply →
Absolutely. I used to work in a C++ shop writing mission critical software. We would be far more concerned to let a newcomer to contribute on existing C++ codebase than on existing Rust codebase. The newcomer surely would have a harder time to make a pull request that compiles and passes tests in Rust than in C++, but that is a good thing for maintainers.
(At least there is no UB in Brainfuck..)
Several successor languages have kept the simple syntax of C while eliminating a large class of warts. Hindsight and not having to keep a wide reaching set of compiler standards let a language have simple syntax and not so many problems with UB.