2017-02-20 8 views
2

私は(という野心的な)テキストエディタに取り組んでいる、と私はこのような何か、テキスト・バッファを表示するには、任意の垂直方向と水平方向の分割を実装しようとしている:私のように表され、この構造を持っているネストされたデータ構造を持つ貸借チェッカーを癒すにはどうすればよいですか?

 buffer 
----------------- 
buffer | 
-------| buffer 
buffer | 

バイナリツリー型のもの:vが垂直分割である

h 
/\ 
    v b 
/\ 
b h 
/\ 
    b b 

は、h水平分割され、そしてbはバッファです。コード形式で

、それはこれです:

pub enum LayoutNode { 
    Buf(Buffer), 
    Split(Box<Split>), 
} 

pub enum Split { 
    Vertical(LayoutNode, LayoutNode), 
    Horizontal(LayoutNode, LayoutNode) 
} 

pub struct Buffer { 
    content: String, 
    // more buffer-related stuff 
} 

すべてが順調です。私の垂直分割方法:

impl LayoutNode { 
    pub fn vertical_split(layout: LayoutNode) -> LayoutNode { 
     LayoutNode::Split(Box::new(Split::Vertical(layout, LayoutNode::Buf(Buffer::new())))) 
     // Buffer::new() returns an empty Buffer 
    } 
} 

この関数はコンパイルしますが、全体的な話ではありません。私は、エディタのレイアウトノードを担当するデータ構造を持っている、Editorと呼ばれる:私はmem::replaceを見て

impl Editor { 
    pub fn new() -> Editor { 
     Editor { 
      buffers: LayoutNode::Buf(Buffer::empty()), 
      // more editor-related stuff 
     } 
    } 

    pub fn vertical_split(&mut self) { 
     // buffers needs to be a part of itself 
     self.buffers = LayoutNode::vertical_split(self.buffers); 
     // cannot move out of borrowed content ^
    } 
} 

撮影したが、私はそれが私は、ネストされたデータ構造を持つ。この場合のために必要なものだということはよく分かりません。 E0507rustc --explainページはこの点であまり役に立ちません。

この場合、借用チェッカーを使用するにはどうすればよいですか?私はむしろすべてを複製したくないでしょう。それは、各分割時にすべてのファイルの新しいコピーで多くのメモリを簡単に無駄にするからです。

答えて

3

mem::replaceは、このような状況でフィールドをダミーに設定するためによく使用されますが、新しい値を生成している間は有効な値です。これは、スレッドが新しい値を生成している間にパニックになった場合、デストラクタは同じオブジェクトを2回解放しないことを保証するために必要です。あなたのケースでは

、それは次のようになります。

impl Editor { 
    pub fn new() -> Editor { 
     Editor { 
      buffers: LayoutNode::Buf(Buffer::empty()), 
     } 
    } 

    pub fn vertical_split(&mut self) { 
     // buffers needs to be a part of itself 
     self.buffers = LayoutNode::vertical_split(
      mem::replace(&mut self.buffers, LayoutNode::Buf(Buffer::empty()))); 
    } 
} 

それはこのように動作します:mem::replaceを交換する変数やフィールドへの変更可能なリファレンスと割り当てる値を受け取り、古い値を返します。 。結果の所有権を取得するので、自由に移動することができます。

+0

これを正しく理解すれば、 'mem :: replace'を使って' self.buffers'に割り当てられた値は、 'vertical_split'を使って割り当てられると破棄されますか?メモリを無駄にしたくない場合は、空のバリアントを 'LayoutNode'に追加できますか? – SuperCheezGi

+1

はい、 'mem :: replace'によって' self.buffers'に移動された値は 'vertical_split'が返ってから代入が実行されると上書きされます。そして、もし 'Buffer :: empty()'が "高価"ならば、あなたは空のバリアントを 'LayoutNode'に追加したいかもしれませんが、そのタイプの全てのマッチはそれを"扱う "必要がありますそれを 'unreachable!()'としてコーディングします)。 –

関連する問題