until文はwhile文の逆で、条件が偽である間処理を繰り返す制御構文です。「〜になるまで繰り返す」という表現を自然に書くことができます。unless文がif文の逆であるように、until文はwhile文の逆の関係にあります。この記事ではuntil文の基本からwhile文との比較、実践的な使い方を解説します。
基本的な使い方
until文は条件式が偽(false)の間、ブロック内の処理を繰り返します。条件が真になるとループを終了します。
count = 1
until count > 5
puts "#{count}回目"
count += 1
end
puts '終了'1回目
2回目
3回目
4回目
5回目
終了「count > 5が真になるまで繰り返す」、つまりcountが6になった時点でループが終了します。while文で書くとwhile count <= 5と同じ意味になりますが、until文の方が「5を超えるまで」という意図が明確です。
whileとuntilの比較
同じ処理をwhile文とuntil文で書き比べてみましょう。
# while版:条件が真の間繰り返す
i = 0
while i < 3
puts "while: #{i}"
i += 1
end
puts '---'
# until版:条件が真になるまで繰り返す
j = 0
until j >= 3
puts "until: #{j}"
j += 1
endwhile: 0
while: 1
while: 2
---
until: 0
until: 1
until: 2while i < 3とuntil i >= 3は同じ意味です。どちらを使うかは「どちらが自然に読めるか」で判断します。
後置until
1行で書ける場合は、後置untilが使えます。
n = 1
n *= 2 until n > 100
puts n128n *= 2 until n > 100は「nが100を超えるまでnを2倍にし続ける」という意味です。1, 2, 4, 8, 16, 32, 64, 128と増えていき、128で条件が真になりループが終了します。
実践的な使い方
目標達成までの繰り返し
# レベルアップシミュレーション
level = 1
exp = 0
required_exp = 100
until level >= 5
gain = 30 + level * 5
exp += gain
if exp >= required_exp
level += 1
exp -= required_exp
required_exp = (required_exp * 1.5).to_i
puts "レベルアップ! Lv.#{level}(次のレベルまで: #{required_exp}EXP)"
end
end
puts "最終レベル: #{level}"レベルアップ! Lv.2(次のレベルまで: 150EXP)
レベルアップ! Lv.3(次のレベルまで: 225EXP)
レベルアップ! Lv.4(次のレベルまで: 337EXP)
レベルアップ! Lv.5(次のレベルまで: 505EXP)
最終レベル: 5データの蓄積
# 配列にデータを追加して閾値に達するまで繰り返す
data = []
sum = 0
until sum >= 50
value = data.length * 3 + 1
data << value
sum += value
puts "追加: #{value} / 合計: #{sum}"
end
puts "データ数: #{data.length}"
puts "データ: #{data.inspect}"追加: 1 / 合計: 1
追加: 4 / 合計: 5
追加: 7 / 合計: 12
追加: 10 / 合計: 22
追加: 13 / 合計: 35
追加: 16 / 合計: 51
データ数: 6
データ: [1, 4, 7, 10, 13, 16]untilは「〜になるまで」「〜に達するまで」という条件に最適です。until finished(完了するまで)、until count >= limit(制限に達するまで)のように、ゴール条件を直接書けるため意図が明確になります。
whileは「条件が真の間」、untilは「条件が真になるまで」と、ループの継続条件が逆です。混同するとバグの原因になるため、「どちらを使えば自然に読めるか」を基準に選びましょう。
まとめ
untilは条件が偽の間繰り返す(whileの逆)- 「〜になるまで繰り返す」という表現に最適
- 後置untilで1行に書くこともできる
while !条件とuntil 条件は同じ意味- 読みやすさを基準にwhileとuntilを使い分ける