saba1024のブログ

どうでも良い思いついた事とかプログラミング関係のメモとか書いていきます。

Rustでクロージャを使ってカウンターを実装するサンプル

クロージャのお勉強用のお題としてよくある、「ある関数から、実行する度に値をインクリメントして返すクロージャを生成して返す」をRustで実装してみました。
RustのクロージャはちょっとApache Groovyなどと比べると癖が有って難しい印象です...(所有権とかが絡んでくるので)
理屈を理解することは当然大切ですが、この辺りはもう慣れっていうのも大事なのかな〜と思って最近は色々小さいコードをRustで書いて色々実験しています。

fn create_counter() -> Box<FnMut() -> i32> {
    // カウンタのデフォルト
    let mut x = 0;

    // 変数xはスタック上に確保されるので、moveを使ってxのコピーの所有権をクロージャに移してあげる。
    let clj = move || {
        x += 1;
        x
    };

    // Rustは、クロージャを返す場合にはBoxで包んで返して上げる必要がある。
    Box::new(clj)
}

fn main() {

    let mut counter1 = create_counter();
    debug_assert!(counter1() == 1);
    debug_assert!(counter1() == 2);
    debug_assert!(counter1() == 3);

    let mut counter2 = create_counter();
    debug_assert!(counter2() == 1);
    debug_assert!(counter2() == 2);
    debug_assert!(counter2() == 3);
    debug_assert!(counter2() == 4);
    debug_assert!(counter2() == 5);

    // 当然別のクロージャが持っている環境(変数)に影響なし。
    debug_assert!(counter1() == 4);
    debug_assert!(counter1() == 5);
}