while ループ
Rの while ループは、条件が TRUE である限り本体を実行し続けます。for ループが何かの要素ごとに1回実行するのに対し、while は条件が変わるまで何回かわからない回数だけ実行します。
すべての while ループを成立させる3つの要素があり、ここにはその3つとも現れています。
- ループの前の準備 —
count <- 1が条件に判定対象を与えます。 - 条件 — おなじみの比較演算子から作られた
count <= 5。毎回の実行前に判定されます。 - 本体の中の更新 —
count <- count + 1がループを終了へ近づけます。
3つ目を削れば条件は永遠に TRUE のままで、ループは終わりません。それが while の本質的なリスクであり、このページの残りは主にその管理についての話です。
条件は毎回の実行の前に判定される
while は先に条件を判定し、それから本体を実行します。ここから2つの帰結が生まれます。開始時点ですでに条件が FALSE なら、本体は0回実行されます。
そして判定は本体の途中ではなく、1回分の実行と実行の間で行われます。ひとたび実行が始まれば、途中で条件が FALSE になっても最後まで走ります。本体の途中で抜けたいときのために break があります(後述)。
実例:しきい値を下回るまで半分にする
while の自然な居場所は「〜になるまで続ける」です。何回で終わるか事前にはわからないので、for は当てはまりません。1000を1未満になるまで、何回半分にできるでしょうか。
10回の半減で、最終的に約0.977になります。「本体が縮めていく状態変数と、増やしていくカウンタ」というこのパターンは、実際の while ループの大部分をカバーします。誤差が十分小さくなるまで走る数値解法、資源が尽きるまで走るシミュレーション、呼び出しが成功するまで続くリトライなどです。
repeat + break:Rのdo-while
Rに do-while のキーワードはありません。本体の後で条件を判定するループが存在しないのです。しかし無条件に永久に繰り返す repeat と、どんなループでも即座に抜ける break があります。repeat の本体の末尾に break の判定を置けば、まさにdo-while——本体が少なくとも1回は実行されるループ——ができあがります。
本体は最初の判定より前に必ず実行されるので、n は少なくとも1回は倍にされます。ループは100を超える最初の倍数である128で抜けます。「まずやる、それからもう一度やるか決める」が正直な説明になる場面——入力が妥当になるまで読む、条件を満たすものが出るまで標本を引く——ではこのかたちを使いましょう。到達可能な break のない repeat は構造上の無限ループなので、先に break を書いてから本体を埋めるのがコツです。
break は while でも for でもまったく同じように働きます。汎用の「ここで終わり」の出口であり、本体の途中の条件を判定するif文と自然に組み合わさります。
while ループの中の next
next は現在の実行の残りを飛ばし、条件の判定へ戻ります。for と同じように while でも機能しますが、while 特有の罠がひとつあります。更新のステップが next の後ろにあると、それを飛ばすことでループ変数が進まなくなり、無限ループができてしまうのです。更新は next より前に置きましょう。
これは2から10までの偶数を表示します。i <- i + 1 を next の行より下に移すと、最初の奇数の時点で更新が永遠に飛ばされてしまいます。for ループではこの危険は存在しない(ループ変数が自動的に進む)ので、単に列を歩くだけなら for を選ぶ理由がまたひとつ増えます。
無限ループへの備え
すべての無限ループは同じバグです。条件が依存する変数を本体の何も変えていないか、間違った方向に変えているのです。対話的に実行していればEscやCtrl+Cで中断できますが、スクリプトではプロセスがただ固まります。防ぐ習慣が2つあります。
1つ目。条件を書いたらすぐに「本体のどの行がこれをFALSEへ近づけるのか?」と自問し、その行が本体を通るすべての経路で実行されることを確かめること(上記の next の罠に注意)。
2つ目。終了が簡単には証明できないループには、最大反復回数のガードを加えること。そうすればロジックのバグは、セッションのフリーズではなく診断できる結果として現れます。以下ではコラッツ風のループ——偶数は半分にし、奇数の x は 3 * x + 1 にして、1に到達するまで繰り返す——を守っています。
10から始めると、ループは6ステップで1に到達します。仮にある開始値が1に到達しなくても、steps < 10000 の節がループを終わらせ、表示された状態が何かおかしいと教えてくれます。目に見える誤った答えは、決して答えないプログラムに勝ります。ここでは短絡評価の && が正しい演算子です。両辺とも単一の値であり、ガードが1つの文として読めるからです。
while と for:どちらを選ぶか
目安は「事前に何がわかっているか」です。
- 何を巡回するかがわかっている(ベクトルの要素、1からnまでの数)→ forループ。ループ変数が自分で面倒を見てくれます。
- 停止条件しかわからない(収束するまで、しきい値を下回るまで、妥当になるまで)→
while。 - どんな判定より先に、本体を必ず1回は実行しなければならない → 終了用の
breakを伴うrepeat。
ベクトルを歩くためだけに while ループの中で手作業のカウンタを管理しているなら、それは変装した for ループです。切り替えましょう。
この記事のまとめ
while (condition) { ... }は先に判定して実行します。開始時に条件が偽なら実行は0回です。- 本体は条件を
FALSEへ近づけなければなりません。準備/条件/更新の三点セットがすべてです。 - Rにdo-whileのキーワードはありません。
repeat { body; if (done) break }が定型で、最低1回の実行を保証します。 breakはどんなループも抜けます。whileでnextを使うときは、飛ばす前にループ変数を更新しないと永遠に進みません。- 最大反復回数のガード(
&& steps < 10000)は、潜在的なハングを目に見えるデバッグ可能な誤答に変えてくれます。
次はベクトルです。このページのすべてのループが歩いてきたデータ構造であり、Rの多くのループがまるごと消えてなくなる理由でもあります。
よくある質問
Rのwhileループはどう動きますか?
while (condition) { ... } は条件を先に判定し、それがTRUEである間だけ本体を実行します。本体の中の何かがいずれ条件をFALSEにしなければなりません。通常はカウンタを更新するか値を小さくします。そうしないとループは終わりません。開始時点で条件がFALSEなら、本体は0回実行されます。
Rにdo-whileループはありますか?
キーワードとしてはありません。定型は repeat { ...body...; if (condition) break } です。repeat は無条件に繰り返すので本体は必ず1回は実行され、末尾の break がdo-whileの脱出判定の役割を果たします。
Rで無限ループを止めるには?
対話的に実行しているなら、Esc(RStudio)またはCtrl+C(ターミナル)で中断します。そもそも起こさないためには、本体が毎回条件に含まれる変数を更新していることを確認し、最大反復回数のガード(while (working && steps < 10000) のように)を加えましょう。そうすればロジックのバグはセッションのフリーズではなく誤った回数として現れます。