This article is written for Rust programmers learning C. As someone
in the opposite position I know C and I've been curious about Rust I'd love to read the reverse.
What's the hardest thing for a C programmer to unlearn when moving
to Rust? Is it the borrow checker, or is that just the thing people
talk about because it's the most visible?
In C, mostly you think about your code running on the machine with some thought dedicated to the compiler gymnastics involved during the compilation phase.
With Rust, you are front loaded with a myriad of compiler gymnastics you need to think through.
But once you get comfortable enough, it becomes natural. You also have to get accustomed to writing code that is more verbose than C which might look ugly at first but later you start to accommodate it as the necessary cost for the utility you are handed in return by the compiler.
For example, multiple variables in Rust doesn't necessarily mean multiple memory allocated variables at runtime like in C. The rust compiler will usually keep track of and ensure multiple variables (non Copy types such as String with Move semantics) map to one memory allocated variable at runtime (in normal single threaded use cases under normal circumstances without using RC, ARC, etc.). Eg: let a = String::from("hello"); let b = a; ... Note: The example is for illustration purposes only and not always true. In summary source code variables are abstractions and may not belong to distinct runtime memory location. Yes it is true even for C. But Rust's ownership model makes that distinction aggressively visible.
I'll offer a thought, which amounts to rephrasing "front loaded with a myriad of compiler gymnastics you need to think through." from sibling.
There's a _lot_ of utility in things that aren't represented by a literal difference in the compiled code. It's not unusual to make a type in Rust that's just a single field; you're not making a struct to gather related data together, you're giving it a different name because the same data means something different.
It's a little like the difference between a uintptr_t and a uint16_t*. They're represented the same in the machine, the difference only exists in the source language.
Rust derives a lot of value from things that only mean something at compile time. I think you'd "unlearn" what C (commonly) teaches when you don't find a C struct with one member "weird".
With Rust, you are front loaded with a myriad of compiler gymnastics you need to think through.
But once you get comfortable enough, it becomes natural. You also have to get accustomed to writing code that is more verbose than C which might look ugly at first but later you start to accommodate it as the necessary cost for the utility you are handed in return by the compiler.
For example, multiple variables in Rust doesn't necessarily mean multiple memory allocated variables at runtime like in C. The rust compiler will usually keep track of and ensure multiple variables (non Copy types such as String with Move semantics) map to one memory allocated variable at runtime (in normal single threaded use cases under normal circumstances without using RC, ARC, etc.). Eg: let a = String::from("hello"); let b = a; ... Note: The example is for illustration purposes only and not always true. In summary source code variables are abstractions and may not belong to distinct runtime memory location. Yes it is true even for C. But Rust's ownership model makes that distinction aggressively visible.
There's a _lot_ of utility in things that aren't represented by a literal difference in the compiled code. It's not unusual to make a type in Rust that's just a single field; you're not making a struct to gather related data together, you're giving it a different name because the same data means something different.
It's a little like the difference between a uintptr_t and a uint16_t*. They're represented the same in the machine, the difference only exists in the source language.
Rust derives a lot of value from things that only mean something at compile time. I think you'd "unlearn" what C (commonly) teaches when you don't find a C struct with one member "weird".