我似乎陷入了被称为"与借阅检查者打架的洞#34;在这一个。我有以下功能:
fn draw_pair(decks: &(&mut Deck, &mut Deck)) -> (Card, Card) {
let (&mut p1, &mut p2) = decks;
(p1.draw_card(), p2.draw_card())
}
我收到以下错误:
expected type: &(&mut Deck, &mut Deck)
found type: (_, _)
这个想法是将可变引用作为元组的内容。我认为没有理由改变元组本身。该函数将循环运行。
我尝试过编写let &(&mut p1, &mut p2) = decks;
,但它告诉我它无法摆脱借来的内容。
这是调用draw_pair
的函数:
fn play(decks: (Deck, Deck)) {
loop {
let cards = draw_pair(&decks);
// actual game not yet implemented
}
}
这也给了我一个错误,说它预计会&(&mut Deck, &mut Deck)
,但会得到&(Deck, Deck)
。
答案 0 :(得分:1)
由于您无法摆脱借来的可变引用,因此您必须克隆这些字段。
fn main() {
play((&mut Deck(0), &mut Deck(0)));
}
#[derive(Clone)]
struct Deck(i32);
fn play(decks: (&mut Deck, &mut Deck)) {
let cards = draw_pair(&decks);
}
fn draw_pair(decks: &(&mut Deck, &mut Deck)) -> (i32, i32) {
let mut p1 = decks.0.clone();
let mut p2 = decks.1.clone();
(0, 0)
}
此处有一个保留play
签名的Playpen和here's a version。
老实说,我认为在这种情况下,添加一个新类型来表示元组将是一个更清晰和可读的解决方案。
理想情况下,我会这样做:
struct Deck {}
struct Card {}
#[derive(Debug)]
struct Pair<T> {
first: T,
second: T,
}
impl<T> Pair<T> {
pub fn new(first: T, second: T) -> Pair<T> {
Pair { first: first, second: second }
}
}
fn play(decks: Pair<Deck>) {
let mut decks = decks;
let cards = draw_pair(&mut decks);
}
fn draw_pair(decks: &mut Pair<Deck>) -> Pair<Card> {
Pair::new(Card {}, Card {})
}
答案 1 :(得分:1)
每当您想使用模式匹配和解构获取引用时,请使用ref
instead of &
。请改用let (ref mut p1, ref mut p2)
,然后取消引用deck
。
您必须注意,您不能改变不可变数据。您既可以使用自己的可变克隆,也可以在没有突变的情况下工作。在decks
中使play
可变是获取draw_pair
中内部数据的可变引用的唯一方法。以下代码解决了您的问题:
fn draw_pair(decks: &mut (Deck, Deck)) -> (Card, Card) {
let (ref mut p1, ref mut p2) = *decks;
(p1.draw_card(), p2.draw_card())
}
fn play(mut decks: (Deck, Deck)) {
loop {
let cards = draw_pair(&mut decks);
// actual game not yet implemented
}
}
如果您在decks
中收到的play
对是不可变的,那么除了维护您自己的克隆和可变Deck
之外没有别的办法了解@wimh在他的回答中。如果您想更简洁地创建自己的可变克隆,以下一个衬垫将有所帮助:&(&mut decks.0.clone(), &mut decks.1.clone())
答案 2 :(得分:0)
这是第一个错误:
8 | let (&mut p1, &mut p2) = decks;
| ^^^^^^^^^^^^^^^^^^ expected reference, found tuple
|
= note: expected type `&(&mut Deck, &mut Deck)`
= note: found type `(_, _)`
解决这个问题的最简单方法是取消引用正确的大小(*decks
),但是你得到了另一个错误:
8 | let (&mut p1, &mut p2) = *decks;
| ^^^^^--
| | |
| | hint: to prevent move, use `ref p1` or `ref mut p1`
| cannot move out of borrowed content
正如使用ref
暗示的那样:
let (&mut ref p1, &mut ref p2) = *decks;
但是没有必要完全解构左侧,你也可以使用
let (ref p1, ref p2) = *decks;
这是一个minimum implementation来重现您的问题,并应用了修复程序:
struct Card{}
struct Deck{}
impl Deck {
fn draw_card(&self) -> Card { Card {}}
}
fn draw_pair(decks: &(&mut Deck, &mut Deck)) -> (Card, Card) {
let (ref p1, ref p2) = *decks;
(p1.draw_card(), p2.draw_card())
}
fn main() {
println!("Hello, world!");
}
编辑:这是play
函数的解决方案,无需修改它的签名:
struct Card{}
#[derive(Clone)]
struct Deck{}
impl Deck {
fn draw_card(&self) -> Card { Card {}}
}
fn play(decks: (Deck, Deck)) {
loop {
let (ref deck1, ref deck2) = decks;
let mut deck1 = deck1.clone();
let mut deck2 = deck2.clone();
let decks = (&mut deck1, &mut deck2);
let cards = draw_pair(&decks);
// actual game not yet implemented
}
}
fn draw_pair(decks: &(&mut Deck, &mut Deck)) -> (Card, Card) {
let (ref p1, ref p2) = *decks;
(p1.draw_card(), p2.draw_card())
}
fn main() {
play((Deck{}, Deck{}));
}