第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がやっと出てきた!イテレータだけで何個もパターンがあって覚えられない...。
今週のプルリクエストはこちら。