2週間ぶりの第26回です。
前回はこちら。
[第26回の様子]
2022/01/26に第26回を開催した。
1/19に元々開催予定だったが、自分が急な発熱でダウンした結果(コロナは陰性)その日はRust雑談の会(回?)が開催された。社内でのRustの使い所とか、参考書籍の紹介があったらしい。実践Rust入門とかプログラミングRust 第2版とか。
第26回の内容としてはRust By Example 日本語版の「9.2.2. 捕捉時の型推論」に取り組んだ。
参加者は9人。参加者が増えて嬉しい😊
[学んだこと]
- 9.2.2. 捕捉時の型推論
- クロージャの話の続き。
- 前回は、クロージャが外部の変数を捕捉する時に、参照、可変参照、値のいずれかの形をとる、という話をした。
- 今回は、クロージャを引数にとる時に、クロージャの型がどうなるか、という話。
- クロージャが参照を捕捉する場合にこのクロージャを引数にするとき、Fn()型になる
fn apply<F>(f: F) where F: Fn() { f(); } fn main() { let greeting = "hello"; let diary = || { println!("I said {}.", greeting); }; apply(diary); }
- クロージャが可変参照を捕捉する場合にはFnMut()型になる
// mut修飾子が必要 fn apply<F>(mut f: F) where F: FnMut() { f(); } fn main() { let mut farewell = "goodbye".to_string(); let diary = || { // farewellの値を変更している farewell.push_str("!!!"); println!("Then I screamed {}.", farewell); }; apply(diary); }
- クロージャが値を捕捉する場合にはFnOnce()型になる
fn apply<F>(f: F) where F: FnOnce() { f(); } fn main() { use std::mem; // to_owned()はコピーでなく移動が起きる型を作る let farewell = "goodbye".to_owned(); let diary = || { println!("Then I screamed {}.", farewell); mem::drop(farewell); }; apply(diary); // ↑で移動しているので2回目に呼び出すとコンパイルエラー:error[E0382]: use of moved value: `diary` // apply(diary); }
- ちなみに、
where
でトレイトを指定しているが、関数名の後の<>
のところで指定しても同じ意味になる
fn apply_to_3_v1<F>(f: F) -> i32 where // Fは引数がi32で戻り値がi32の関数 F: Fn(i32) -> i32 { f(3) } // 先に型を指定することもできるが全体像が掴みづらくなるかも... fn apply_to_3_v2<F: Fn(i32)->i32>(f: F) -> i32 { f(3) } fn main() { let double = |x| 2 * x; println!("3 doubled: {}", apply_to_3_v1(double)); println!("3 doubled: {}", apply_to_3_v2(double)); }
- このあたりのことはテキストのもう少し先で詳しく出てきそう
[まとめ]
モブプログラミングスタイルでRust dojoを開催した。
参照とか値の話が出てくるたびに、Rustのコンパイラは賢いなあ...と思う。
今週のプルリクエストはこちら。