there is no horror in c++. it is a better investment of your time IMHO to learn patterns and best practices and learn how things work at a low level instead of learning a language like rust which attempts to hide difficult work from you and make your life easier. in the end you will pay for that when you finally understand there are no shortcuts and you really need to understand how the machine, memory management and…
Tell HN: Rust Is Complex
61–70 of 102 posts
Re: Tell HN: Rust Is Complex
#62I too program in rust, however I don't like programming in rust. It feels like C++ on steroids. I consider all the meta-programming and traits mostly read only. There's too many concepts you have to understand and wrappers on top of wrappers. And even when you know what you want to do, it's sometimes a huge fight to get rust to understand what you are doing. Even with unsafe this process can be really annoying and fr…
To address some of your complaints: yes, there are a lot of concepts to understand. I like wrappers, I found it crazy that in C, you first declare a mutex_t variable, and then you specifically have to call chMtxObjectInit(*mutex_t mutex) to initialise it [1]. If you forget? UB, kernel panic sometime in the future. I think Mutex::new() is far cleaner, and it's namespaced without arbitrary function prefixes. Binaries are tiny in comparison to JS/Python with deps, they will be larger than C. Compile times aren't that slow and you can't make extra language features happen out of thin air.
In C, I've found that it's commonplace to do a lot of clever and mysterious pointer and memory tricks to squeeze out performance and low resource utilisation. In embedded, there's usually a strong inclination to using "global" static variables, even declaring them inside function bodies because it "limits the visibility/scope of the variable". Not declaring a static variable inside a function is what knocked a few points off my Bachelor's robotics project.
I personally don't like this. It puts a lot of pressure on the programmer to understand the order of execution, and keep a complex mental model of how the program works. Large memory allocation, such as a cache, can be hidden in just about any function, not just at the top of a file where global variables are usually defined.
It sounds like what you're trying to accomplish is inherently unsafe, hence the "preaching", as in it requires the programmer's guarantee that 1) the data is fully initialised before it's accessed and 2) once the data is initialised, it's read-only and can therefore safely be accessed from other threads. C doesn't care, it will let you do a direct pointer access to a static variable with no overhead. Where's the cost? The programmer's mental model. I haven't tried, but I imagine that Rust's unsafe block will allow you to access static variables, just like in C with no overhead, effectively giving your OK to the compiler that you can vouch for the memory safety.
Rust solutions: lazy_static crate (safe, runtime cost in checking if initialised on every access), RwLock> (safe, runtime cost to lock and unwrap the option), unsafe (no overhead, memory model cost and potentially harder debugging), extra &T function parameter (code complexity cost, "prop-drilling", cleaner imo). On modern hardware, the runtime cost is absolutely negligeable.
Why would you not want to use Rust for a large project? This seems a bit contradictory to me. The safety guarantees in my opinion really pay off when the codebase is large, and it's difficult to construct that memory model, especially with a team working on different parts. Instead, you overload that work to the compiler to check the soundness of your memory access in the entire codebase.
If you like C, by all means keep on using it, I enjoyed my forray into C, it's simple and satisfying, but would much prefer Rust, after spending a lot of time tracking down memory corruption. Rust's original design purpose was to reduce memory bugs in large-scale projects, not to replace C/C++ for the fun of it. We usually have a natural inclination to what we know well and have used for a long time. Feel free to correct me if something is wrong.
1: http://www.chibios.org/dokuwiki/doku.php?id=chibios:document...
Re: Tell HN: Rust Is Complex
#63I too program in rust, however I don't like programming in rust. It feels like C++ on steroids. I consider all the meta-programming and traits mostly read only. There's too many concepts you have to understand and wrappers on top of wrappers. And even when you know what you want to do, it's sometimes a huge fight to get rust to understand what you are doing. Even with unsafe this process can be really annoying and fr…
I don't want to come off dogmatically defending Rust, I code little Rust in comparison to JS, and I've done C and C++ for some embedded systems. C is a very different monster to most other languages, I find people defending C to be just as proud and defensive as Rust programmers. To address some of your complaints: yes, there are a lot of concepts to understand. I like wrappers, I found it crazy that in C, you first…
I stand that rust is more fun to write when you work higher level, treat it higher level language, where you'll have less control over the memory model of program. It all starts breaking down and you need to become a "rust low-level expert" when you want to work closer to the memory model (copy-free, shared memory, perhaps even custom synchronization / locking models ...). It does make sense, but in my opinion figuring out how to map your own model into rust concepts is not trivial, it requires lots of rust specific knowledge, which will take a long time to learn IMO.
When unsafe was marketed to me, I thought it was a tool I could use to escape the clutches when I'm sure what I'm doing and don't want rust to fight me, but sadly it doesn't work that way in practice, but the real way is to actually write C and call it from rust.
Re: Tell HN: Rust Is Complex
#64Earlier quoted context omitted.
I don't want to come off dogmatically defending Rust, I code little Rust in comparison to JS, and I've done C and C++ for some embedded systems. C is a very different monster to most other languages, I find people defending C to be just as proud and defensive as Rust programmers. To address some of your complaints: yes, there are a lot of concepts to understand. I like wrappers, I found it crazy that in C, you first…
The point was none of those rust crates worked, or required you to use mutex in the end which the solution would not actually need (not zero-cost abstraction). I would've fine using unsafe, but even with unsafe it felt like I was fighting the compiler. I would just write this particular function with C, or use the lower level C FFI functions instead. I stand that rust is more fun to write when you work higher level,…
I also agree with your other statement. I think Rust tries to abstract a lot of behind into its own type system, such as Box for pointers, whilst keeping it relatively fast. C is definitely the right tool for the job if you want direct memory access, I also think this is a relatively small proportion of people, working on OS, embedded systems or mission critical systems such as flight control/medical equipment.
Re: Tell HN: Rust Is Complex
#65I get the sentiment, but one thing that probably needs to be underlined here is that one only needs to face that complexity if you really want to, however. Otherwise you can just wrap everything in Arc, Cow and similar helpers and call it a day. Even lazy Rust code can still be incredibly performant, testable and fault tolerant. The lower level you go, the more you need to know about Rust and how what it does maps to…
> Otherwise you can just wrap everything in Arc, Cow and similar helpers and call it a day. … which is how we got slow, bloated legacy C++ codebases today, should we make the same mistake with Rust? If you are wrapping everything in ref-counted smart pointers it might probably be better to just use a garbage-collected language like Java or C# instead…
Re: Tell HN: Rust Is Complex
#66- noisy syntax
- concerning and very bad compiler performance
I can definitely see Swift replacing Rust in the short term, Apple seems to be committed
Re: Tell HN: Rust Is Complex
#67Earlier quoted context omitted.
Do you have more examples? I’ll admit that Go is full of weird quirks, but nothing feels bolted on. Generics were agonized over for so long because they had to fit it within the existing language
Here’s one: The fact that contexts are used extensively in the standard library but that there’s still no way to cancel a write to an io.Writer. The only way to “cancel” a write on a TCP socket is to set the socket’s “deadline” to some time in the past from another goroutine.
If you want a much more annoying example of inconsistency in the initial language design, look at the behaviour of nil and closed channels:
- sending data to a nil channel blocks forever;
- receiving data from a nil channel blocks forever;
- sending data to a closed channel causes a panic;
- receiving data from a closed channel is fine: you receive the zero value, forever.
I can understand the logic behind the last two (sending to a closed channel is an error in program logic, and closing a channel is a common idiom for broadcasting completion of a task to several goroutines), but the first two are just a massive footgun, and, in my opinion, should cause panics instead.
Re: Tell HN: Rust Is Complex
#68I think I need someone to explain Rust async to me. I think I understand that await causes the half of function to be rewritten into a state machine that returns immediately to caller and the promise object implements the rest of the control flow. I don't understand waiters, pollers.
When you don't want to block your process and program in a reactive, non-blocking way, which is what futures and promises are an implementation of, what you are actually defining is something like this:
> "our process will do some synchronous work, then it will need to stop at point X to wait for asynchronous data"
> "after that data arrives, we can restart our process where it stopped, at point X, and do some more work until it hits point Y, where it will need to wait some more asynchronous data"
> "after that also completes, we can restart from Y, and process until the end of the function"
However, the problem that arises is _how do you store the variables that are being used in this function_? Particularly those values that would be saved in the stack, because by returning the function, the program needs to pop all those stack frames so that the caller can continue executing.
There are two ways of accomplishing this. The first way is to use stackful co-routines, aka threads. The OS does this, but platform threads have very high overhead, so many languages avoid it. You can also use the OS's reactive APIs or thread pools and implement your own scheduler with virtual threads on top, which is what Go or Erlang (and soon Java) do, but then you can't avoid that runtime overhead, which Rust and C++ don't want to have, or maybe you want a more lightweight model (which Javascript wanted).
In that case, the other approach you can do is explicitly represent the processes' variables and state as a structure in the heap, and create functions that operate on those structures. In Javascript you can easily do this (you can capture the values in a closure), and in Rust it is more complicated but doable, and in general you can do this in most languages.
The downside here is that, instead of being able to simply code your process in a straightforward way and have it block implicitly, you need to explicitly code the synchronous steps between each asynchronous wait, which results in either callback hell, confusing functional styles such as continuation passing, or future combinators and callbacks.
What async lets you do, then, is have the compiler write those state machines for you. If you mark your function as async, the compiler will create the closure for you, the state transitions for you, deal with waiting for nested futures for you, and so on, and you can just write the code in the 'dumb' synchronous style. This is common to all the async implementations, from Rust to JS to C#.
However, at some point, you need to actually drive these state machines. You need some kind of scheduling that is able to receive external events, get the state machine that is waiting for it, and execute the next state transition. Driving these state machines is done using those waiters and pollers. Rust exposes these APIs, because it does not bundle the executor, and so it exposes those methods so that async runtimes like tokio can be built against a standard API. Javascript, on the other hand, still needs to perform those tasks but, because it has a runtime of its own, implements an execution service implicitly, and so the external interface of Promise does not need to expose that concern.
Re: Tell HN: Rust Is Complex
#69there is no horror in c++. it is a better investment of your time IMHO to learn patterns and best practices and learn how things work at a low level instead of learning a language like rust which attempts to hide difficult work from you and make your life easier. in the end you will pay for that when you finally understand there are no shortcuts and you really need to understand how the machine, memory management and…
Rust doesn’t handhold you for anything low-level. It’s just that Rust hides all that complexity beneath Unsafe Rust, which is an eldritch language that no one quite knows all the rules yet (including things related to undefined behavior…) I hope the MiniRust project ( https://github.com/RalfJung/minirust ) succeeds in writing a formal spec of it someday.
what is more important is to understand how to architecturally build software and achieve performance and maintainability and so on. i rather spend my limited hours becoming better in a language like c or c++ which is not going away anytime soon than learning syntax, a new way of thinking and a package management system i don’t need.
Re: Tell HN: Rust Is Complex
#70Rust have nice ideas but the execution is very poor - noisy syntax - concerning and very bad compiler performance I can definitely see Swift replacing Rust in the short term, Apple seems to be committed