Open3

Rust XXX

kchokcho
fn run() {
    let foo: Rc<Cell<i32>> = Rc::new(Cell::new(50));
    println!("value: foo={}", foo.get());
    println!("ref counter: {}", Rc::strong_count(&foo));
    let bar = Rc::clone(&foo); // clone and increment ref counter
    println!("ref counter: {}", Rc::strong_count(&foo));
    let hoge = Rc::clone(&foo); // clone and increment ref counter
    println!("counter: {}", Rc::strong_count(&foo));

    bar.set(100);
    println!(
        "value: foo={}, bar={}, hoge={}",
        foo.get(),
        (*bar).get(), // also can get from deref value
        hoge.get()
    );

    drop(bar);
    println!("ref counter: {}", Rc::strong_count(&foo)); // descrimented
}

Cell 制約

  • Cellの中身の型はCopyトレイトを実装する必要がある
  • Cellは参照やスマートポインタなどを含め、スレッド間でやりとりすることができない
  • Cellは中身の参照を取ってくることができない
kchokcho

マルチスレッドでの排他制御では Arc x Mutex をつかう

fn run() {
    // use Arc<Mutex<T>> for multi thread atomic access
    let a = Arc::new(Mutex::new(vec![1, 2, 3]));
    let b = Arc::clone(&a);
    let c = thread::spawn(move || {
        b.lock().unwrap().push(10);
    });
    dbg!(Arc::strong_count(&a), &a);
    // thread の終了を待って、aが更新され、参照が消えてることを確認
    c.join().unwrap();
    dbg!(Arc::strong_count(&a), &a);
}
kchokcho

イテレータ

以下の b, c, d, e は同じように書ける。

fn run() {
    let a = [1, 2, 3, 4];

    let b = a.iter().filter(|&&x| x % 2 == 0).fold(1, |acc, x| acc * x);
    let c = a.iter().filter(|x| **x % 2 == 0).fold(1, |acc, x| acc * x);
    let d = a.iter().filter(|&x| x % 2 == 0).fold(1, |acc, x| acc * x);
    let e = a.iter().filter(|x| *x % 2 == 0).fold(1, |acc, x| acc * x);
    dbg!(b, c, d, e);
}

配列やコレクションは Iterator trait を実装してる。iter() は各要素の不変参照のイテレータを返す。さらに flter も各要素の不変参照を取るので filter に渡すので filter に渡すクロージャの引数の型は &&i32
b のパターンは明示的にデリファランスを2回行って、クロージャのbody内で i32型 の値を扱っている。
c のパターンは デリファランス演算子(*) によって body 内でデリファランスを行っている。
d, e はパッと見だと一度しかデリファランスしてないように見える。
Rust にコンパイラによって、filterに渡すクロージャの引数は自動でデリファランスされるため、 d, e のような書き方ができる(こちらのほうがよく見る)