Why can't I mutate this HashMap - References in Rust

2024-01-06

Note: This is an older video I made for TikTok and never posted as a TIL so posting now

In a discord I'm in someone just posted this question about Rust.

I'm trying to iterate through the keys of a hash map in rust. And then if a certain thing is true, change the value of that key. I don't see why we need to clone the keys. Since I'm only changing values. Is there a way to get around cloning? And here's the code that they left in that snippet?

And the answer to the specific question was to you, something like iter_mut() to loop over the iterator and still be able to edit the data underneath. But that alone doesn't really explain why, why do we need to clone the keys before we can change the values of the map? If you don't do this, Rust will complain about having an immutable borrow to keys when trying to create a mutable borrow for the insert method call. And if you're not really used to references and Rust, that can sound like a bunch of gibberish.

So let's try an analogy. We have some data, let's say it's a list of numbers and we want to remember it. So we take our own personal whiteboard and we write down our list of numbers. And now we want to share this list with Frank. We don't want to give Frank our whole whiteboard. We just want them to have the list of numbers. So we take a piece of paper out and we write down the list of numbers. And this is our reference. Frank can take this piece of paper and with just that he can read the list of numbers that we have on our whiteboard.

And Frank can now share this with Kim. He can take a photocopy of this piece of paper, give it to Kim. And now Kim can see the list of numbers that we have on our whiteboard to. But what if we want to add a number to this list? We could just walk to our whiteboard and write a new number down. But now Kim and Frank's papers, aren't going to be right. They're not going to know about this extra number we added. And so Rust is going to stop us Rust. Isn't going to let us write on our whiteboard just yet. We have to make sure all of the pieces of paper, all of the references are cleaned up first. So if all of those pieces of paper are thrown away and Rust doesn't see any pieces of paper anywhere, now we can finally write on our whiteboard again and change the data.

So if we go back to the sample code that we were looking at before, when we asked for the keys that was creating a reference, we've got a piece of paper with all the keys in our hash map. So since we have that reference, that piece of paper, we can't add new things to the hash map and we can't change the values of anything. Because we have a reference to it. So, what we need to do is we need to get rid of that reference and how we are doing that is we're cloning it. So we take that list. That's on our piece of paper and basically we rewrite it down on our whiteboard and now it's a separate piece of data we could add to it separately than our hash. And then things like might be out of whack. We might have something in one list that isn't in the other, but as far as Rust is concerned, those are two completely separate pieces of data. So we took the reference and put it on our whiteboard, and then we threw away that piece of paper and got rid of the reference. And now we're allowed to mutate our hash map again, because there are no references hanging around. There are no pieces of paper. We just have the one data structure and we can mutate it as we, as we want.

Hopefully that analogy was helpful to someone. And this helps explain Rust references to you. Let me know in the comments, if this helped you out or if it didn't, I'd like to know how we can do something better next time. Thanks.

coreyja weekly

My weekly newsletter tailored at developers who are eager to grow with me!
Every week will be unique, but expect topics focusing around Web Development and Rust