2017-08-04 1 views
0

私はいつも私を借りチェッカーと競合させる私の錆のプログラムのパターンにつまずいています。次のおもちゃの例を考えてみましょう:錆の照合と借用チェッカー

use std::sync::{Arc,RwLock}; 

pub struct Test { 
    thing: i32, 
} 

pub struct Test2 { 
    pub test: Arc<RwLock<Test>>, 
    pub those: i32, 
} 

impl Test { 
    pub fn foo(&self) -> Option<i32> { 
     Some(3) 
    } 
} 

impl Test2 { 
    pub fn bar(&mut self) { 
     let mut test_writer = self.test.write().unwrap(); 

     match test_writer.foo() { 
      Some(thing) => { 
       self.add(thing); 
      }, 
      None => {} 
     } 
    } 

    pub fn add(&mut self, addme: i32) { 
     self.those += addme; 
    } 
} 

Someアームでadd機能がすでに読み書きを開くためにちょうど一致ステートメントの上immutably借りた、mutably自己を借りしようとするので、これはコンパイルされません。ロック。

主にRwLockを使用しているときに、このパターンがRustで数回発生しました。また、matchステートメントの前にブール値を導入し、次にSomeアームのブール値を変更して、最終的には、このブール値のテストをマッチステートメントの後に導入して、何でもしたいSomeアームで実行します。

それはそれを行う方法ではないと思うが、私はRustでこれを行うより慣用的な方法があると思うか、まったく異なる方法で問題を解決する。私が間違っていないならば、問題は字句借用と関係しているので、selfは、マッチステートメントの武器内で可変的に借りることはできません。

この種の問題を解決する慣習的な錆の方法がありますか?

答えて

2

カスタム型を持つ例えば直接利用分野those、:

use std::sync::{Arc,RwLock}; 

pub struct Those(i32); 

impl Those { 
    fn get(&self) -> i32 { 
     self.0 
    } 

    fn add(&mut self, n: i32) { 
     self.0 += n; 
    } 
} 

pub struct Test { 
    thing: Those, 
} 

pub struct Test2 { 
    pub test: Arc<RwLock<Test>>, 
    pub those: Those, 
} 

impl Test { 
    pub fn foo(&self) -> Option<Those> { 
     Some(Those(3)) 
    } 
} 

impl Test2 { 
    pub fn bar(&mut self) { 
     let mut test_writer = self.test.write().unwrap(); 

     match test_writer.foo() { 
      Some(thing) => { 
       // call a method add directly on your type to get around the borrow checker 
       self.those.add(thing.get()); 
      }, 
      None => {} 
     } 
    } 
} 
+0

慣用的な解決策。 –

1

あなたはどちらかself

pub fn bar1(&mut self) { 
    let foo = self.test.write().unwrap().foo(); 
    match foo { 
     Some(thing) => { 
      self.add(thing); 
     }, 
     None => {} 
    } 
} 

または直接を変異させると非借りを変異させる前に、selfの一部のボローを終了する必要がありますself

pub fn bar2(&mut self) { 
    let test_writer = self.test.write().unwrap(); 

    match test_writer.foo() { 
     Some(thing) => { 
      self.those += thing; 
     }, 
     None => {} 
    } 
} 
+0

ありがとうred75prime。 Boiethiosの答えを正しいものとして受け入れるつもりです。なぜなら、私は彼が「慣用的」な部分に答えたように思えるからです。しかし私のコードでは、あなたの最初の提案の変種を使用します。) – Vincent

+0

@Vincentあなたが使用しなければならない解決策は、コードの複雑さに依存します。それが本当に複雑な場合は、必要のない借用の数を最小限に抑えるためにすべてを行います。さもなければあなたは遅かれ早かれ借りチェッカーと戦うでしょう。 – Boiethios

関連する問題