for
イテレータに対してループ処理を行う場合はfor
を利用します。一番シンプルなケースはRange
オブジェクトを使用するパターンです。Range
オブジェクトは..
を使うと簡単に作成できます。
fn main() {
for i in 0..5 {
println!("i: {}", i);
}
}
「イテレータ」はIterator
トレイトのインスタンスであること、を指しています(ややこしい)。
普段は(少なくとも筆者は)あまり意識することはありませんが、JavaScriptにもイテレータの概念があります。詳しくはイテレーターとジェネレーターを参照してください。
配列やベクタのようなコレクションに対してもfor
を使用できます。注意点として、単にfor
に対してコレクションを渡すとデフォルトでは暗黙的にそのコレクションのinto_iter
が呼び出されます。この方法では、コレクションの各要素は直接使用されます。すなわち、コレクションの要素の所有権はループに移るため、ループの後にコレクションを参照することはできません。
fn main() {
let numbers = vec![1, 2, 3];
for num in numbers {
println!("num: {}", num);
}
// println!("{:?}", numbers); // エラー: 所有権が移動している
}
これを防ぐには、明示的にiter
を呼び出します。この方法では、各ループで要素の参照を借用するので、所有権は移動しません。
fn main() {
let numbers = vec![1, 2, 3];
for num in numbers.iter() {
println!("num: {}", num);
}
println!("{:?}", numbers); // 問題なく参照可能
}
while
イテレータ関係なく、指定の条件を満たす限りループ処理を続行したい場合はwhile
を使用します。
fn main() {
let mut counter = 0;
while counter < 5 {
println!("counter: {}", counter);
counter += 1;
}
}
if
と同様に、Option
な値(Some
かNone
の値)を扱いたいが、None
のときは何もしたくないケースではwhile let
構文を使用できます。
fn main() {
let mut numbers = Some(5);
while let Some(num) = numbers {
println!("num: {}", num);
numbers = if num > 1 { Some(num - 1) } else { None };
}
}
loop
while(true)
と同等の働きをします。条件判定の処理がないので、若干高速です。
fn main() {
let mut count = 0;
loop {
if count >= 5 {
break;
}
println!("count: {}", count);
count += 1;
}
}
loop
は値を返すことができます。break
の後に値を書いておくと、その値をloop
を抜けた後に使用できます。ユースケースとして、処理が成功するまでリトライするものが挙げられます。
fn main() {
let mut attempts = 0;
let result = loop {
attempts += 1;
if attempts == 3 {
break "Success!";
}
};
println!("Result: {}", result);
}
ループを飛ばしたいとき、抜けたいとき
各ループを次に飛ばしたいときはcontinue
を使用します。また、途中でループそのものを抜け出したい場合はbreak
を使用します。
fn main() {
for i in 0..10 {
if i % 2 == 0 {
continue; // 偶数をスキップ
}
if i > 7 {
break; // 7を超えたらループを終了
}
println!("i: {}", i);
}
}