2016-12-18 5 views
0

私は「借りチェッカーと戦う」という穴に落ちたようです。私は次のエラーを取得する入力パラメータとしてのタプルへの参照の変更

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

&(Deck、Deck)をdraw_pair関数に渡していますが、予想される&(&mut Deck、&mut Deck)ではありません。 。 – SplittyDev

+0

@SplittyDev私はそれを認識しています。 –

+0

@SplittyDev私が手元に持っているデータは、デフォルトでは不変です –

答えて

1

ref instead of &を使用しています。代わりにlet (ref mut p1, ref mut p2)を使用し、deckを参照解除してください。

不変のデータを変更することはできません。独自の可変クローンを使用することも、突然変異を起こさずに作業することもできます。をplayに変更することは、draw_pairの内部データへの変更可能な参照を取得する唯一の方法です。あなたはplayで受け取るdecksペアは不変である

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 
    } 
} 

場合は、その周りに他に方法はありませんが、@wimhが彼の答えでないように、独自のクローン化され、変更可能なDeck Sを維持するために、次のコードは、あなたの問題を解決します。 &(&mut decks.0.clone(), &mut decks.1.clone())

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; 

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機能のためのソリューションであるdが完全に適用される修正して、あなたもここで

let (ref p1, ref p2) = *decks; 

はあなたの問題を再現するために minimum implementationで使用することができ、左側をdestructureします

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{})); 
} 
+0

私の質問を更新しました –

+0

'mut'リファレンスが必要です。それは 'let(ref mut p1、ref mut p2)' – EvilTak

+0

@ElectricCoffeeでなければなりません。新しい質問を追加するのではなく、新しい質問をするのが良いですが、私は答えに可能な解決策を含めました。私はあなたの正確な要件を知らないので、私はそれがあなたのために働くかどうかはわかりません。将来的に問題を再現する[最小、完全、および検証可能](http://stackoverflow.com/help/mcve)の例を含めることを検討してください。 – wimh

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署名を保存しPlaypenhere'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 {}) 
} 
+0

これは理想的な解決策ではありません。 'let mut decks = decks'を動作させる行は悪いハックです。これはどうしても避けてください。このような小さなアプリケーションでは違いはありませんが、マルチスレッド/同時のシナリオではそうなります。不変であるものは、何らかの費用で突然変異してはならない。 – EvilTak

+0

これはどのようにして避けなければならないものですか?ペアを所有しているため、変更可能な参照を取得することができます。これは決して問題を引き起こすことはありません。マルチスレッドのシナリオでは、Cell またはMutex を使用して、とにかく同期しています。あるいは、ペアをmut mut Pair に変更しても問題ありません。 – SplittyDev

関連する問題