【Rust入門】繰り返し処理(for, while, loop)を分かりやすく解説

Rust における 繰り返し処理(for
, while
, loop
)の基本について初心者にも分かりやすく解説します。
Rust の繰り返し処理
プログラミングでは、繰り返し処理(ループ)は、複数回の処理を効率よく実行したいときに欠かせないものです。Rustには主に、for
、while
、loop
といった3種類のループ構文があります。
この記事では、それぞれの繰り返し処理の使い方の基本について紹介していきます。
for による繰り返し処理
for の基本構文
Rust の for
文の基本構文は以下のようになります。
for
の基本構文for 要素 in イテレータ { // 繰り返したい処理 }
Rust の for ループは、C/C++ 等の多くの言語のようにインデックスを増やしていき繰り返すのではなく、イテレータによって制御されることが特徴です。Python に触れたことがある方はなじみがある方法です。
ここでいう「イテレータ」とは、繰り返し可能なシーケンスを表すオブジェクトで、for はその要素を1つずつ取り出して処理をしていきます。例えば、数値の範囲(0..5
)や、配列・ベクタ(Vec<T>
)などのコレクションはイテレータとして扱うことができます。
私自身、以前は C/C++ や Java といったインデックスベースの for
ループに慣れていたため、最初にイテレータベースの Python に触れたときは少し違和感を感じました。しかし、慣れてくるとインデックス管理のわずらわしさがなく、構文もすっきりしていてとても合理的だと感じるようになりました。Rust についても同様のイテレータベースの for
を採用しているため、最初は戸惑うかもしれませんが一度仕組みを理解すれば安全性と可読性を両立できる強力な構文だと分かると思います。
数値の範囲による繰り返し
以下の簡単な例で for
の使い方を見ていきましょう。
fn main() { // forによる繰り返し for i in 0..5 { println!("i = {}", i); } }
i = 0 i = 1 i = 2 i = 3 i = 4
上記例では、i
に 0
から 4
までの値を順に取り出し、順に表示していきます。
0..5
は、「0
以上 5
未満」のイテレータを表します。なお、末尾の数値は含まれません。末尾の数値を含みたい場合は 0..=5
とすることで「0
以上 5
以下」となります。
配列やベクタ(Vec<T>)を使った繰り返し
配列やベクタ(Vec<T>
)を使ったfor文の繰り返し例についても見ておきましょう。
【配列の場合】
fn main() { // forによる繰り返し(配列を使う場合) let num_array = [2, 4, 5]; for num in num_array { println!("{}", num); } }
【実行結果】 2 4 5
【ベクタ(Vec<T>)の場合】
fn main() { // forによる繰り返し (Vecを使う場合) let fruits = vec!["apple", "banana", "blueberry"]; for fruit in fruits.iter() { println!("{}", fruit); } }
【実行結果】 apple banana blueberry
いずれの例もそれぞれの配列やベクタの先頭から順に要素を取り出して表示ができていることが分かります。
Vec<T>
で .iter()
を使っている理由上記例で気付いた方がいるかもしれませんが、Rust の for
ループでは、配列 [T; N]
は、”イテレータ”の部分にそのまま書いていますが、ベクタ Vec<T>
については .iter()
を使っています。
これは Rust の所有権という独自仕様に関係しています。Rustでは、Vec<T>
をそのまま for
に渡すと、.into_iter()
が自動的に呼ばれ、要素と一緒に Vec
自体の所有権が移動します。そのため、ループ後に Vec
変数が使えなくなります。一方で、.iter()
は読み取り専用の不変参照 (&T
) として扱う方法で、元のベクタを消費せずに済み、ループ後に Vec
変数が使えなくなってしまうことを避けられます。
所有権は Rust の中核的な仕組みですが、最初は少し難しく感じるかもしれません。今の段階では「Vec<T> を使うときは .iter() をつける」ぐらいで覚えておくだけでも十分です。
break/continue による繰り返しの制御
繰り返しの最中には一定の条件になった場合には、繰り返し処理を終了したり、後続の処理をスキップしたりしたい場合があります。その際には break
文や continue
文を使用します。なお、これらの文は以降で紹介する while
や loop
でも使用できるのでここで紹介しておきます。
break
:ループを終了するcontinue
:後続の処理を実施せずに次の繰り返しにスキップする
以下の例は、0..10
の数値シーケンスを表示していくのですが、i
が 2
の時はスキップし、i
が 5
になったらループを終了するような例です。
fn main() { // break, continue による繰り返しの制御 for i in 0..10 { if i == 2 { continue; // 後続の処理をスキップ } if i == 5 { break; // ループを終了して抜ける } println!("i = {}", i); } }
【実行結果】 i = 0 i = 1 i = 3 i = 4
出力結果を見ると i = 2
はスキップされており、i = 5
の際にはループを抜けるため 5
以降の数字は表示されていないことが分かります。
while による繰り返し処理
while の基本構文
Rust の while
文の基本構文は以下のようになります。
while
の基本構文while 条件 { // 条件がtrueの間、処理を繰り返す }
while
ループは、条件が満たされている限り繰り返す構文です。ループの回数が決まっていないときや、外部の変数、関数の結果などに応じて繰り返すような場面でよく使用します。
例えば以下の例では、数字が5になるまで表示を繰り返します。
fn main() { let mut n = 1; // whileによる繰り返し while n <= 5 { println!("n = {}", n); n += 1; } println!("終了"); }
【実行結果】 n = 1 n = 2 n = 3 n = 4 n = 5 終了
loop による繰り返し処理
loop
の基本構文
Rust の loop
文の基本構文は以下のようになります。
loop
の基本構文loop { // 明示的に break するまで無限ループで繰り返す }
loop
は、無限ループを意図的に書く構文です。他の多くの言語には存在しない Rust 特有の明示的な無限ループです。break
を使用して自分でループの終了タイミングを制御する必要があります。
基本的な loop
の使用方法
以下の例で loop
の基本的な使用方法を見てみましょう。
fn main() { let mut count = 0; // loopによる無限ループ (breakが必要) loop { // 5以上の場合、ループを終了する if count >= 5 { break; } println!("count = {}", count); count += 1; } }
【実行結果】 count = 0 count = 1 count = 2 count = 3 count = 4
上記の例では、count
を増やしつつ 5 以上の条件に一致したら break
で繰り返しを終了します。loop
の処理では無限ループであるため、break
を記載しないと処理が終わらないことに注意して使用してください。
loop
の値の返却
他の for
や while
による繰り返しとは異なり、loop
だけが break
によって値を返すことができます。
以下の例では、上記の処理と同じですが処理結果を返却しています。
fn main() { let mut count = 0; // loopのbreak時に値を返却する let result = loop { if count >= 5 { break true; } println!("count = {}", count); count += 1; }; println!("result : {}", result); }
【実行結果】 count = 0 count = 1 count = 2 count = 3 count = 4 result : true
値を返却する際には「break 値;
」のように記載します。while
や for
のループでは、break
に値を指定することはできませんので注意してください。
while
による無限ループよりも loop
を使用する
無限ループは、以下のように while
で書き換えることができます。
while true { // 無限ループの処理 }
ただし、Rustでは while true
よりも loop
を使用することが一般的であり、コンパイル時には以下のような警告でアドバイスをしてくれます。(※旧バージョンだと表示されない可能性があります)
warning: denote infinite loops with `loop { ... }` | 5 | while true { | ^^^^^^^^^^ help: use `loop` |
理由は、loop
は無限ループだという意図が一目でわかることがあげられます。loop
は無限ループを明示するための専用構文であるため、読みやすさだけでなく break
を書く必要があることが明確で、場合によって値を返すこともできるという柔軟さも持ち合わせています。
そのため、Rustでは「無限ループ = loop
」と覚えておくとよいでしょう。
まとめ
この記事では、Rust における繰り返し処理の基本として、for
、while
、loop
の3つの構文について解説しました。
for
はイテレータベースのループで、安全かつ簡潔にコレクションを処理できます。while
は条件が満たされている間だけ繰り返す処理に適しており、状態に基づくループに便利です。loop
は明示的な無限ループを実現でき、break
によってループを抜けるだけでなく、値を返すこともできる柔軟な構文です。
Rustのループ構文は、所有権や安全性といったRustの特徴を踏まえた設計になっており、最初は戸惑う部分もあるかもしれませんが、使い方に慣れることで安全かつ効率的なコードを書くことができるようになります。
繰り返し処理はあらゆるプログラムで登場する重要な要素ですので、基本をしっかり身につけていただけたらと思います。