2週間ぶりの第26回です。
前回はこちら。
[第26回の様子]
2022/01/26に第26回を開催した。
1/19に元々開催予定だったが、自分が急な発熱でダウンした結果(コロナは陰性)その日はRust雑談の会(回?)が開催された。社内でのRustの使い所とか、参考書籍の紹介があったらしい。とかとか。
第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のコンパイラは賢いなあ...と思う。
今週のプルリクエストはこちら。