Hacker News new | ask | show | jobs
by attractivechaos 1262 days ago
Nice blog post. Nonetheless, to a new learner like me, the hardest part of rust is not its syntax; it is the ownership management. Sometimes I easily know how to implement a task efficiently in other languages but I have to fight the compiler in rust. I either need to reorganize data structures, which takes effort, or to make a compromise by cloning objects, which affects performance. Note that I do agree with rust designers that it is better to make data dependencies explicit but learning to deal with them properly is nontrivial for me.
3 comments

This is exactly why I prefer Rust, eh, for everything. It forces you to think harder about your data structures and to better organize/understand your program and how data flows, gets consumed and get output.

You can ignore that in other languages, but this comes at a cost later.

My experience with Rust data structures is the opposite. To satisfy lifetime analysis inherent in pointer-based data structures, users tend to introduce additional indirection. For example, mapping keys to indexes, and then indexes to array elements, instead of simply mapping keys to values.
I've used Rust quite a bit, but I would love to hear more about this. Is this comparing to lower level languages like C/C++/Zig, or higher level GC'd languages? What problems does it make us think more about up-front, and do you think it's due to single ownership (in the C++ and Rust sense) or the borrow checker?
If you think about programming as information transformation (ie: you are getting information in, applying a certain transformation and then giving some output), programming becomes about how this information flows. Data structure becomes the most important thing.

Here is an example that now frustrates me about JavaScript. I don't know if some variables "MyVal" declared somewhere is global, local or how transfer it around. Global variables no longer makes sense to me. In Rust, global variables are possible but they are obvious and their scope is completely within your control. Now, all the data is there and it's up to you how to structure it, move it around, store it, etc.. You have to think these through before doing any code. If you don't think well enough, the Rust compiler (borrow/ownership thing) will start to give you headaches.

The short answer is... yeah, just clone the objects. Whatever other languages are doing is going to have the same tradeoff - performance (or safety, if the other languages aren't memory safe). Iff it becomes a problem, come back later and remove the '.clone()'.
You can also use Cow<> to choose between cloning and and immutable borrowing at runtime.
Unless you're using `'static` you will still run into lifetimes with Cow, which I suspect a lot of people will find difficult. I'd suggest just using clone, learning the broader language, and learning about lifetime stuff later.

Lifetimes aren't hard or complicated, what's complicated is understand their interaction with other features (closures) when you don't even understand wtf closures in rust are, or traits, etc. I'd just focus on the other stuff for as long as you can.

> Lifetimes aren't hard or complicated,

Untrue - read https://users.rust-lang.org/t/what-is-a-good-mental-model-of.... Even Rust aficionados can't describe how they work without vast screeds. Or if you think the posters there are just wrong, try the RFC on which the current implementation is based: https://rust-lang.github.io/rfcs/2094-nll.html. You truly don't find that hard or complicated?

It may be the case that people can use simplified subsets of the language to ease their way. But when a Rust advocate says that in effect to understand lifetimes you have to read the standard library source (as is written in the forum thread linked above), because no current documentation is comprehensive enough to cover it, then you know the whole thing itself is pretty complex.

> You truly don't find that hard or complicated?

This is like saying: "You think a 64bit integer is simple? OK, let's dig into the C memory model, twos complement, overflow CPU flags, how CPU caches are implemented, architectural nuances that can lead to unsynced writes from registers to RAM, etc". In reality most people can just learn that it's a number that holds 2^64 values, not complicated. If you want to really understand integers though go read the intel manual and the C memory model specification.

Are lifetimes complicated? If you're a compiler developer who needs to consider the implications across all features and edge cases, yes. If you're learning the language and you just want to write "find me a &str in another &str but don't clone it", no, it's not complicated at all.

The vast majority of beginners can just learn "& means any number of readers and no writers, &mut means one writer and no readers".

> The vast majority of beginners can just learn "& means any number of readers and no writers, &mut means one writer and no readers".

But 'beginning' is never the hard part of learning any programming language, at least for a programmer. The hard part is going from having learned the basics to getting stuff done. Rust is harder than any other mainstream language to do that in. The writers in that thread can't even describe their mental model (NOT the underlying tech as you claim) of lifetimes without vast elliptical descriptions. And they can't point to any straightforward documentation.

I have learned multiple programming languages, of many different paradigms, and never had the trouble getting to the stage of writing useful software that I have had with Rust. I've witnessed the same again and again with all the people I know - all professional programmers. In fact I'm the only one I know who's stayed with it.

I find the denial of Rust's difficulty (and not even centred on the borrow checker - it's the use of just about every commmon library) just very very strange. Odd enough (and distant enough from the obvious, adn the experience of every person I've known) that I find it completely incomprehensible.

But it's so easy to get a handle on how the borrow checker works! Just check out this thread and all will become clear: https://users.rust-lang.org/t/what-is-a-good-mental-model-of...

Joke btw. That thread is a hilarious trainwreck - surely the final nail in the coffin for the Rust advocates who so often deny anything about Rust is difficult to learn.

I don't mean that as an anti-Rust jibe, in fact I'm planning to get back to it this year (having given up in despair last). I like much about it, and think it's tremendously practical for many purposes. But it just is a difficult language, no question.

I mean, some question. I learned Rust with 0 professional experience in any language (I learned it after I dropped out of a CS program after 2.5 years) and I found it pretty damn easy. That was in 2015 when the language was wayyyy less approachable (worse borrow checker, everything used nightly, smaller community, no book).

Easy is relative. I suspect a major reason I found it easy was because I didn't try to solve lifetime problems, I just cloned things. I also had primarily been using C++ in school so I was pretty familiar with pointers and, to some extent, ownership. Plus my initial foray into CS was driven by a desire to do exploit development professionally, so lower level details weren't scary at all.

> Easy is relative

In the case of programming languages, yes, it's relative to the difficulty of other PLs. I've learned many over the years, and found Rust by far the hardest (it's the only one that defeated me). And it's not the most different from others I've learned - lisps are far further from the common languages than Rust is.

> I suspect a major reason I found it easy was because I didn't try to solve lifetime problems,

Well yes anything's easy if you skip the hard bits. Learn C without using pointers.

I personally didn't find ownership & borrows the hardest part - in my case it's the great complexity of many of the commonly used libraries. Rust's complexity bleeds out into the entire ecosystem (a cultural thing).

> In the case of programming languages, yes, it's relative to the difficulty of other PLs.

I've learned many many PLs at this point. Rust was one of the easiest for me.

> Well yes anything's easy if you skip the hard bits. Learn C without using pointers.

That's my entire point. Rust is not hard if you learn the easy parts first. Trying to learn everything at once is not easy, no matter the language. Once the problem becomes just learning the borrow checker it's not that big of a deal. The harder thing to do is learning the borrow checker and traits and closures and blah blah blah.