2016-06-21 11 views
6

クローズの状態にはいくつかのデータがありますが、どのように変更可能にするのですか?たとえば、毎回インクリメントされた値を返すカウンタクロージャが必要ですが、機能しません。私はそれをどのように機能させるのですか?可変状態をクロージャに移動するにはどうすればよいですか?

fn counter() -> Box<Fn() -> i32> { 
    let mut c: i32 = 0; 
    Box::new(move || { 
     c += 1; 
     c 
    }) 
} 

fn main() { 
    let mut a = counter(); 
    let mut b = counter(); 
    println!("{:?}", [a(), a(), a(), b(), b(), a()]); 
} 

エラー(警告)私は取得しています:

error: cannot assign to captured outer variable in an `Fn` closure 
     c += 1; 
     ^~~~~~ 
help: consider changing this closure to take self by mutable reference 
    Box::new(move || { 
     c += 1; 
     c 
    }) 

は私が[1, 2, 3, 1, 2, 4]のような出力に何かにそれを期待しています。

答えて

8

エラーメッセージが言うように:FnMutとして

fn counter() -> Box<FnMut() -> i32> { 
    let mut c = 0; 
    Box::new(move || { 
     c += 1; 
     c 
    }) 
} 

fn main() { 
    let mut a = counter(); 
    let mut b = counter(); 

    let result = [a(), a(), a(), b(), b(), a()]; 
    println!("{:?}", result); 

    assert_eq!([1, 2, 3, 1, 2, 4], result); 
} 

Fn閉鎖する代わりに

で撮影し、外側の変数に代入することはできません、あなたはFnMut閉鎖をしたいですdocs:

変更可能な受信者を取るコールオペレータのバージョン。

これにより、クロージャが包含状態を変更することができます。

なお、cの明示的な型は必要ありません。私を混乱させる何


は、そのpub trait Fn<Args>: FnMut<Args>です。 Fn(私が使用したもの)がFnMutの動作をサポートするはずですか?

恐らくWhen does a closure implement Fn, FnMut and FnOnce?は、背景情報を提供するのに役立ちます。これは直感的に分かりますが、どのようにコミュニケーションをとるのが最適かわかりません。 Finding Closure in Rustからこのセクションでは、関連すると思われる:ハイレベルself

は実装(ユーザーが形質を実装するために定義即ちタイプに)次及び&self少なくともフレキシブル&mut self最も柔軟性を与えます。逆に、&selfは、消費者に特徴(すなわち、形質によって限定されたジェネリックを有する機能)の特性を最も柔軟にし、selfを与える。要するに

、その特性の定義はどのFnMut閉鎖がFn閉鎖としてを使用できることを述べています。これは、単に変更可能性を無視できるので、ある意味があります。あなたは他の方法で行くことはできません - あなたは不変の参照を変更可能なものにすることはできません。

+0

ありがとうございました!私を混乱させるのは、そのパブの特徴Fn :FnMut 'です。 'Fn'(私が使ったもの)が' FnMut'の振る舞いをサポートするべきではないのでしょうか? – Shchvova

+2

@Shchvovaが更新されました。 – Shepmaster

関連する問題