Open3
Rust XXX

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は中身の参照を取ってくることができない

マルチスレッドでの排他制御では 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);
}

イテレータ
以下の 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 のような書き方ができる(こちらのほうがよく見る)