第20回です。
前回はこちら。
[第20回の様子]
2021/12/01に第20回を開催した。
内容としてはRust By Example 日本語版の「8.3. while」、「8.4. for と range」に取り組んだ。
参加者は、ちょっと減って、7人だった。
[学んだこと]
- 8.3. while
- 無限ループを作るloopと違って、カウンタを使うwhileも書ける
- FizzBuzzをwhileを使って書くとこうなる
fn main() { // カウンタとなる変数 let mut n = 1; // `n`が101以下である場合のループ while n < 101 { if n % 15 == 0 { println!("fizzbuzz"); } else if n % 3 == 0 { println!("fizz"); } else if n % 5 == 0 { println!("buzz"); } else { println!("{}", n); } // カウンタに1を追加 n += 1; } }
- loopでは
break 戻り値;
の形式でloopから値を返すことができたので、whileでも試してみる
fn main() { let _ret = while n < 101 { if n % 15 == 0 { println!("fizzbuzz"); break n; } else if n % 3 == 0 { ... } } // 以下のコンパイルエラー error[E0571]: `break` with value from a `while` loop --> src/main.rs:11:13 | 8 | let _ret = while n < 101 { | ------------- you can't `break` with a value in a `while` loop ... 11 | break n; | ^^^^^^^ can only break with a value inside `loop` or breakable block | help: use `break` on its own without a value inside this `while` loop | 11 | break; | ~~~~~
break;
でブレークすることはできるけど、値を返せるのはloopのみ、と言われてしまった。無念。- 8.4. for と range
- forの条件式としてrangeを用いる方法は2つある
for n in 1..101 { // 1〜100まで } for n in 1..=100 { // 1〜100まで }
- for in構文では3種類のイテレータを使うことができる
- 1つ目は
.iter()
fn main() { let names = vec!["Bob", "Frank", "Ferris"]; for name in names.iter() { match name { &"Ferris" => println!("There is a rustacean among us!"), _ => println!("Hello {}", name), } } println!("{:?}", names); }
- これはコレクションの要素を借用するので、
- 2つ目は
.into_iter()
fn main() { let names = vec!["Bob", "Frank", "Ferris"]; for name in names.into_iter() { match name { "Ferris" => println!("There is a rustacean among us!"), _ => println!("Hello {}", name), } } }
- こちらのやり方の場合、データがループ内に移動するため、matchの方法も参照(&)ではなくなっている
- 移動したデータは使えなくなるため、先ほどのようにprintln!をfor文のあとに追加すると以下のコンパイルエラーとなってしまう
error[E0382]: borrow of moved value: `names` --> src/main.rs:11:22 | 2 | let names = vec!["Bob", "Frank", "Ferris"]; | ----- move occurs because `names` has type `Vec<&str>`, which does not implement the `Copy` trait 3 | 4 | for name in names.into_iter() { | ----------- `names` moved due to this method call ... 11 | println!("{:?}", names); | ^^^^^ value borrowed here after move | note: this function takes ownership of the receiver `self`, which moves `names`
- 3つ目は
.iter_mut()
- これを使うと、コレクション内のデータを変更できる
fn main() { let mut names = vec!["Bob", "Frank", "Ferris"]; for name in names.iter_mut() { *name = match name { &mut "Ferris" => "There is a rustacean among us!", _ => "Hello", } } println!("names: {:?}", names); // forループ後の再利用も問題ない }
[まとめ]
モブプログラミングスタイルでRust dojoを開催した。
基本的なループのforとwhileがやっと出てきた!イテレータだけで何個もパターンがあって覚えられない...。
今週のプルリクエストはこちら。