I seem to have fallen into the hole known as "fighting the borrow checker" on this one. I have the following function:
fn draw_pair(decks: &(&mut Deck, &mut Deck)) -> (Card, Card) {
let (&mut p1, &mut p2) = decks;
(p1.draw_card(), p2.draw_card())
}
I get the following error:
expected type: &(&mut Deck, &mut Deck)
found type: (_, _)
The idea is to take mutable references the contents of the tuple. I see no reason to mutate the tuple itself. This function will be running in a loop.
I've tried writing let &(&mut p1, &mut p2) = decks;
instead, but it tells me it can't move out of borrowed contents.
Here's the function that calls draw_pair
:
fn play(decks: (Deck, Deck)) {
loop {
let cards = draw_pair(&decks);
// actual game not yet implemented
}
}
This too gives me an error, saying it expects &(&mut Deck, &mut Deck)
but is getting &(Deck, Deck)
.
Whenever you want to obtain references using pattern matching and destructuring, use
ref
instead of&
. Uselet (ref mut p1, ref mut p2)
instead, and dereferencedeck
.You have to note that you cannot mutate immutable data. You can either use your own mutable clones, or work without mutation. Making
decks
inplay
mutable is the only way to obtain mutable references to the inner data indraw_pair
. The following code solves your problem:If the
decks
pair you receive inplay
is immutable, there's no other way around it but to maintain your own cloned and mutableDeck
s like @wimh does in his answer. If you want to create your own mutable clone more concisely, the following one liner will help:&(&mut decks.0.clone(), &mut decks.1.clone())