blog.dopana

Back

Rustにおいてループは、単なる繰り返し処理を超えた表現力豊かな制御構造です。一般的な forwhile に加え、値を直接返せる loop 式、パターンマッチングと連携してデータを消費する while let、そして多重ループを的確に制御するループラベルが備わっています。

10歳でもわかる説明:自動販売機とペッツ(キャンディ容器)#

2つのお菓子の仕組みをイメージしてください:

  1. 自動販売機 (loopbreak 値): 大当たりが出るまでコインを投入し続け、当たりが出た瞬間に景品が排出口から直接手元に戻ってきます(break 景品)。
  2. ペッツ容器 (while let Some(キャンディ)): 首を後ろに倒すたびにキャンディがあるか確認します。キャンディが出てくる限り(Some(キャンディ))、食べ続けます。容器が空になった瞬間(None)、自然に食べるのをやめます。
graph TD
    Start["ループ開始"] --> PatternMatch{"式がパターンにマッチするか?<br/>(例: Some(item))"}
    PatternMatch -->|Yes: item を抽出| LoopBody["item を使ってループ本体を実行"]
    LoopBody --> NextEval["次の要素 / 状態を評価"]
    NextEval --> PatternMatch
    PatternMatch -->|No: None / 不一致| Terminate["ループを正常終了"]

式としての loop: 値を返すループ#

C系言語の多くではループは文(statement)ですが、Rustの loop は式(expression)です。break の後ろに値を指定することで、ループから直接値を返すことができます:

graph LR
    LStart["loop 開始"] --> Work["リトライ処理の実行"]
    Work --> Check{"成功条件を満たしたか?"}
    Check -->|No| Work
    Check -->|Yes: break value| ReturnVal["result = 返された値"]

while let: パターンがマッチする間繰り返す#

スタックやキュー、チャネル、イテレータから順次要素を取り出す際、while let を使うことでスマートに記述できます:

冗長な書き方 (loop + match)#

src/main.rs
let mut stack = vec![1, 2, 3];

loop {
    match stack.pop() {
        Some(top) => println!("取り出した値: {top}"),
        None => break, // 空になったら脱出
    }
}
rust

while let による洗練された書き方#

src/main.rs
let mut stack = vec![1, 2, 3];

// stack.pop() が Some(top) を返す限り継続
while let Some(top) = stack.pop() {
    println!("取り出した値: {top}");
}
rust

[!TIP] チャネル受信 (receiver.recv()) やスタックの消費など、NoneErr になるまで継続してデータを取り出す場面では常に while let を検討してください。

ループラベル: ネストした多重ループの制御#

入れ子になったループでは、通常の breakcontinue は最も内側のループにのみ適用されます。ループラベル(シングルクォート ' で始まる名前)を付けることで、外側のループを明示的に指定して脱出できます:

sequenceDiagram
    participant Outer as 外側ループ
    participant Inner as 内側ループ
    
    Outer->>Inner: 内側ループへ進入
    Inner->>Inner: remaining == 9: break 内側
    Inner-->>Outer: 外側ループに戻る
    Outer->>Inner: 内側ループへ進入 count 2
    Inner->>Outer: break counting_up: 外側ループから脱出

ループ構文の比較まとめ#

構文主な用途break 値 対応パターンマッチング
loop無限ループ、リトライ機構、ワーカースレッド対応内部で match と併用
while 条件一般的な真偽値(bool)条件による反復非対応非対応
while let パターンOptionResult のシーケンス消費非対応対応(自動バインド)
for 要素 in イテレータ既知のコレクションや範囲の走査非対応対応(要素の分配束縛)

まとめ#

  • loopbreak 値 により計算結果を直接返すことができます。
  • while let はシーケンスの取り出し処理において冗長な loop + match を完全に解消します。
  • ループラベル('label: loop)により、複雑な多重ループのジャンプ先を正確に制御できます。

参考資料#