3 ms·
In my experience learning Rust (and in watching others learn Rust) that first "aha!" moment is actually rather misleading. That moment comes when one learns ho
by verdagon 4y ago
In my experience learning Rust (and in watching others learn Rust) that first "aha!" moment is actually rather misleading.
That moment comes when one learns how to technically accomplish any task in Rust. One knows the minimum set of tools needed to refactor enough to work around the borrow checker's limitations. Learning what the borrow checker prefers becomes second nature and, as you say, becomes natural.
However, the journey isn't over there. One still has to learn the costs they paid to fit their design into what the borrow checker prefers. For some situations, the cost is low (CLI tools, data transformation, numeric analysis, etc). For other situations, the cost can be alarmingly high: one learns that the borrow checker is surprisingly anti-abstraction, causes brittle APIs, and can sometimes introduce artificial complexity compared to the optimal solution in other languages. One sees this a lot in programs with unavoidable inherent state. There are also sometimes problems working with teams, because the borrow checker likes to cause refactors with very wide blast radii that conflict with others.
Of course, this varies wildly person-to-person, according to the prevalent use of unsafe, Rc, etc.
Understanding how to work within the borrow checker isn't enough. The real challenge comes in figuring out when to work within it, and when to work outside it, in my opinion.
- kibwen 4y ago> The real challenge comes in figuring out when to work within it, and when to work outside it, in my opinion. You don't need to feel bad about "working outside" the borrow checker, and maybe that's a signal that needs boosting. I've been using Rust for ages and I'm not averse to cloning things when I need to. It's cool that you can create zero-allocation libraries by threading lifetimes everywhere, and I certainly appreciate all the library authors who go the extra mile by doing so internally to their libraries, but in my application code it's easy to tell that a given thing isn't going to be a bottleneck and isn't going to be negatively impacted by a little copying and allocating.
- pdimitar 4y agoYep, very much this. I code async CLI apps and I seriously don't care that the CLI args and the data structures they get transformed to are cloned 250 times at startup because after that 99% of the actual heavy-duty code is working with channels and references with nearly zero memory pressure. Memory usage gets bumped up by about 2% after the first 1-2 minutes of operation and it stays constant for next 11 hours during which I've monitored it. I don't even need to benchmark anything. The apps are working ultra fast on a Celeron J450 CPU at ~20MB RAM usage and barely hit 10% CPU (since they're mostly network-bound). No need for premature optimization. I haven't dived in the lifetime hell of Rust yet but I'm already quite productive and I will only be using zero-allocation techniques if my current code proves inadequate the the ever-increasing demand that these apps will soon face.
- mwcampbell 4y agoI figured that working outside the borrow checker meant using unsafe.