Hacker News new | ask | show | jobs
by jeffparsons 1422 days ago
> [...] just hold a reference to the UserAccount itself and modify it at will without any confusion

Except the confusion of data races and having multiple concurrent writers more generally. Not a hypothetical: I've worked in a large C# code base where other people had decided it was fine to just pass a bunch of references around to different long running processes, and sure enough, they ended up stomping over each other's assumptions in really dangerous ways.

Unless of course you're actually controlling access to the data somehow (mutex / read/write lock), in which case you can just use _exactly the same pattern_ in Rust... so this whole thing seems like a bit of a red herring.

> [...] so we work around it by putting all UserAccount instances into a Vec<UserAccount> [...]

No, "we" don't. That's one particular (bad) pattern you could choose, and I wouldn't even say it's an obvious alternative. If in your hypothetical alternative programming language you would have just kept a reference to the data (via GC or ref counting, as you said) then why not do exactly the same thing? `Arc` is a thing. It works just fine.

This sounds like a case of trying to come up with convoluted solutions to simple problems and thereby doing something unnecessarily bad that nobody made you do.

Rust certainly has its warts... but this isn't one of them. Rust doesn't make you do what you're describing, and you could equally choose to do the same bad design in your preferred GC language.

1 comments

That's why I mentioned one needs to have discipline, to not use that particular solution.

We agree it's not the best solution. And it's easy for us to say that now, after I've spelled out why. You'd be surprised how many people don't know that this can be a problem.

Also, it amuses me that having a simple index into a Vec would be a "convoluted solution". It's the easiest solution of all the alternatives. It can also be risky for privacy.

Compare that to a GC'd language, where the easiest solution (just hold a reference) doesn't introduce privacy risks.

Arc is by far the easiest solution. You don't have to deal with indices at all.
In Rust, people tend to go for the easiest solution that works within the borrow checker, and not workarounds like Rc or Arc. Otherwise, the performance hit means there's little reason to use Rust over much easier languages.
Callinc Rc a workaround is like calling i64 a workaround. It is a type that encodes a certain contract, it's there to be used. The advantage Rust has is that for 95% of your codebase the simple code using stack allocated values and references will be as fast as it can be, and yoi opt-into the slower behavior for the remaining 5% if they are not part of your performance critical path. If it is, then you need to rearchitect things, like you would in other languages. But you can do so after meaauring.
You don't have to throw out the baby with the bathwater. A few Arcs to hold onto a Users metadata is hardly going to be in the critical path of the app.
That's where the discipline comes in: one has to know when it's okay to use the simpler approach (indices into a Vec), and when it's better to use Arcs such as to prevent privacy problems.
The point is that we disagree that indices into a Vec is the simple approach. It's much harder. It infects the entire code. Whereas just using a reference count is basically set and forget.