2016-11-15 10 views
4

可変バインディングを変更できる場合に、なぜ再バインド/シャドーイングが必要ですか?考えてみましょう:可変バインディングを変更できるときに、なぜ再バインド/シャドーイングが必要ですか?

let x = a(); 
let x = b(x); 

let mut x = a(); 
x = b(x); 

が変更可能な変数バインディングは、この上でその変数の可変借りすることができます。 しかし、シャドウイングには可変バインディングよりもいくつかの利点がありますか?

答えて

8

2つの効果が全く異なるためです。本当に何が起こっているかを理解するには


は、我々は最初に起動する必要があります:結合されているもの?綴りは何を意味しますか?

簡単な関数を考えてみましょう:fn hello() -> String;

ので、同じようにこの関数を呼び出す:何が起こる

fn main() { 
    hello(); 
} 

この関数はStringを返します。すぐに破棄されます(Dropを実行するとメモリが解放されます)。

変数名にバインドされていないため結果が破棄され、バインドされていなければすぐにをドロップすることができます。

ただし、この結果をバインドすると、この値の存続期間が長くなり、しばらくの間このバインディングを使用してアクセスできます。

fn main() { 
    let value = hello(); 

    std::mem::drop(value); 

    println!("{}", value); // Error: moved out of value 
} 

この手元の問題である:さびで、値の寿命は、結合の範囲から独立しています。

バインディングがスコープを終了する前に、値を削除する必要はなく、別のものに転送することもできます(関数からの戻りと同様)。

fn main() { 
    let x; 
    { 
     let y = hello(); 
     x = y; 
    } 
    println!("{}", x); 
} 

_に結合する場合にも同じことが起こります。


ここで、バインディングと値が異なることを覚えていますので、2つのスニペットを調べてみましょう。

あなたは異なる第シャドウイングスニペット:順に

fn main() { 
    let x = a(); 
    let x = b(); 
} 

ステップ、:

  • 発現a()発現b()が作成x
  • に結合されている値を、作成し値はx
  • で作成された値です。は
  • a()によって作成された値
  • xが再バインドされているという事実は、以前にバインドされた値の寿命に影響を与えないことに注意してください

をドロップされるドロップされます。

b()の結果はyがスコープ内にある間、結合前のxにアクセスできないことを唯一の例外で、yに結合させたかのように技術的には、それが正確に動作します。

さて、可変断片:順に

fn main() { 
    let mut x = a(); 
    x = b(); 
} 

ステップ、:

  • 発現a()b()値を作成x
  • に結合されている値を、作成しxにバインドされ、以前の値(a()によって作成された)が破棄されます。
  • b()によって作成された値が

を落としているもう一度、以前の値にアクセスすることは不可能である(より小さな範囲にシャドーイング場合)、しかし、シャドーイングとしながら、それは一時的に不可能だ、値が削除されるので、割り当てでそれは永遠に不可能です。

+0

ありがとう、あなたはそれを私にもっとはっきりとさせました。 –

+0

@RomanPolach:あなたは大歓迎です:) –

+0

電球をついにつないだ素晴らしい答えです。関数 'fn main(){ }の中で' x = y; 'は使わないでください。 { y = hello(); x = y; } println!( "{}"、x);} 'be' x = y; 'また、 'b'によって作成された値が 'a'によって作成された値の前にドロップされる理由について、私のような初心者に明確にしてください。私はこれを完全に吸収しようとしています。 – Kayote

8

私は自分自身を見つけました。シャドーイングは可変型を変えることができます。

let x = get_some_string(); 
let x = x.smart_parse_int(); 
+3

それだけではありません。 mutabilityを変更することもできます(これは一般的な用途です): 'let mut foo = Foo :: new();/* fooをビルドする*/let foo = foo; // foo immutable'を行います。 – Hauleth

+0

@ŁukaszNiemier:それにブロック式を使うだけでよいことに注意しましょう。 'let foo = {let mut foo = Foo :: new(); ...; foo}; ' –

関連する問題