Rust入門

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

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

Rust における 繰り返し処理(for, while, loopの基本について初心者にも分かりやすく解説します。

Rust の繰り返し処理

プログラミングでは、繰り返し処理(ループ)は、複数回の処理を効率よく実行したいときに欠かせないものです。Rustには主に、forwhileloop といった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

上記例では、i0 から 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 文を使用します。なお、これらの文は以降で紹介する whileloop でも使用できるのでここで紹介しておきます。 

  • break:ループを終了する
  • continue:後続の処理を実施せずに次の繰り返しにスキップする

以下の例は、0..10 の数値シーケンスを表示していくのですが、i2の時はスキップし、i5 になったらループを終了するような例です。

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 の値の返却

他の forwhile による繰り返しとは異なり、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 値;」のように記載します。whilefor のループでは、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 における繰り返し処理の基本として、forwhileloop の3つの構文について解説しました。

  • for はイテレータベースのループで、安全かつ簡潔にコレクションを処理できます。
  • while は条件が満たされている間だけ繰り返す処理に適しており、状態に基づくループに便利です。
  • loop は明示的な無限ループを実現でき、break によってループを抜けるだけでなく、値を返すこともできる柔軟な構文です。

Rustのループ構文は、所有権や安全性といったRustの特徴を踏まえた設計になっており、最初は戸惑う部分もあるかもしれませんが、使い方に慣れることで安全かつ効率的なコードを書くことができるようになります。

繰り返し処理はあらゆるプログラムで登場する重要な要素ですので、基本をしっかり身につけていただけたらと思います。

ABOUT ME
ホッシー
ホッシー
システムエンジニア
はじめまして。当サイトをご覧いただきありがとうございます。
私は製造業のメーカーで、DX推進や業務システムの設計・開発・導入を担当しているシステムエンジニアです。これまでに転職も経験しており、以前は大手電機メーカーでシステム開発に携わっていました。

これまでの業務を通じてさまざまなプログラミング言語や技術に触れてきましたが、その中でもRustの設計思想に惹かれ、この言語についてもっと深く学びたい、そしてその魅力を発信していきたいと思い、このサイトを立ち上げました。

自身の学びを整理しつつ、同じようにRustに興味を持つ方のお役に立てるような情報を発信していければと思っています。どうぞよろしくお願いいたします。

※キャラクターデザイン:ゼイルン様
記事URLをコピーしました