Ruby 入門

Ruby while と until ループ

ループはプログラミングにおける基礎的なコンセプトであり、特定のコードブロックを繰り返しエグゼキュート(実行)することを可能にします。

本章では、Ruby における while および until ループについて探求し、特定のコンディションに基づいてプログラムのフローをコントロールするためのパワフルなアプローチを提供します。

1. while ループ

Ruby における while ループは、指定されたコンディションが true である間、コードブロックを継続的にエグゼキュートします。そのベーシックなシンタックスは以下の通りです:

while condition do
  # エグゼキュートするコード
end

または、より一般的な do を省略した記述法です:

while condition
  # エグゼキュートするコード
end

各イテレーションの前に、プログラムは condition(コンディション)をエバリュエート(評価)します。コンディションが true の場合、ループ内部のコードがエグゼキュートされます。ループ内のコードのエグゼキュートが完了すると、再びコンディションがチェックされます。このプロセスは、コンディションが false になるまでリピートされます。

1.1 ベーシックな while ループのサンプル

1から5までのナンバーをプリントする、while ループを使用したシンプルなサンプルを見てみましょう:

counter = 1 # カウンターのバリアブルをイニシャライズ(初期化)する

while counter <= 5 # コンディション:counter が 5 以下である限り、ループは継続する
  puts counter # counter の現在の値をプリントする
  counter += 1 # counter を 1 インクリメントする (counter = counter + 1 と等価)
end

puts "ループが終了しました!" # これはループがコンプリートした後にプリントされる

このサンプルにおいて:

  • バリアブル counter1 にイニシャライズします。
  • while ループは counter <= 5 が成立するかどうかをチェックします。
  • コンディションが true の場合、counter の値をプリントし、その後 counter を1インクリメントします。
  • ループは counter6 になるまで継続し、その時点で counter <= 5 というコンディションが false になり、ループがターミネート(終了)します。
  • ループ終了後、puts "ループが終了しました!" のコードがエグゼキュートされます。

1.2 無限ループ

非常に重要なポイントとして、while ループのコンディションが最終的に false になることを必ず保証する必要があります。そうでない場合、永遠にランし続ける無限ループをクリエイトしてしまいます。例:

# このサンプルには注意してください - 無期限にランし続けます!
# x = 1
# while x == 1
#   puts "これは永遠にプリントされ続けます!"
# end

このサンプルでは、x は常に 1 と等しいため、x == 1 のコンディションは永遠に true となり、ループは絶対に終了しません。無限ループをストップさせるには、通常マニュアルでプログラムをターミネートする必要があります(例:ターミナルで Ctrl+C を押下する)。

1.3 ユーザーインプットと while ループのコンバイン

while ループは、特定のコンディションが満たされるまで、ユーザーにインプットを継続的にプロンプトするために頻繁にユースされます。例:

input = ""

while input != "quit"
  print "コマンドをインプットしてください ('quit' でターミネート): "
  input = gets.chomp # ユーザーのインプットを取得し、末尾のニューライン(改行)をリムーブする
  puts "あなたのインプット: #{input}" unless input == "quit" # インプットが "quit" でない限り、そのインプットをプリントする
end

puts "プログラムをエグジットしています。"

このサンプルにおいて:

  • input バリアブルを空のストリングにイニシャライズします。
  • input"quit" と等しくない限り、while ループは継続します。
  • ループ内部で、プログラムはユーザーにインプットのコンテンツをプロンプトします。
  • gets.chomp メソッドはユーザーから1行のインプットをリードし、末尾のニューラインキャラクターをリムーブします。
  • その後、インプットされたコンテンツが "quit" でない限り、プログラムはインプットされたコンテンツをユーザーにプリントして返します。
  • ユーザーが "quit" をインプットした時点で、コンディション input != "quit" が false となり、それに伴いループがターミネートします。

1.4 マルチプルなコンディションを持つ while ループ

ロジカルオペレーターである && (AND) や || (OR) を使用して、while ループ内で複数のコンディションをコンバインすることができます。

counter = 1
limit = 10
flag = true

while counter <= limit && flag
  puts "カウンター: #{counter}"
  counter += 1
  flag = false if counter > 5 # counter が 5 を超えた場合、flag を false にセットする
end

puts "ループが終了しました。カウンター: #{counter}, フラグ: #{flag}"

このサンプルでは、counterlimit 以下であり、かつ flag が true である限り、ループは継続します。これらのコンディションのうちいずれかが false になった瞬間に、ループはターミネートします。

2. until ループ

until ループは while ループの真逆のアプローチを取ります。これは指定されたコンディションが false である間、コードブロックを継続的にエグゼキュートします。そのベーシックなシンタックスは以下の通りです:

until condition do
  # エグゼキュートするコード
end

または、より一般的な記述法:

until condition
  # エグゼキュートするコード
end

同様に、各イテレーションの前に condition がエバリュエートされます。コンディションが false の場合、ループ内部のコードがエグゼキュートされます。コードのエグゼキュートが完了すると、再びコンディションがチェックされます。このプロセスは、コンディションが true になるまでリピートされます。

2.1 ベーシックな until ループのサンプル

以前の1から5までのナンバーをプリントするサンプルをリライトしますが、今回は until ループを使用します:

counter = 1

until counter > 5 # コンディション:counter が 5 より大きくない限り、ループは継続する
  puts counter
  counter += 1
end

puts "ループが終了しました!"

このコードがジェネレートするアウトプットは while ループのサンプルと完全に同一ですが、ロジックはリバース(反転)されています。ループは、counter5 より大きくなるまで継続します。

2.2 ユーザーインプットと until ループのコンバイン

while ループと同様に、until ループもユーザーにインプットを継続的にプロンプトするためにユースできます。以前のユーザーインプットのサンプルをモディファイしてみましょう:

input = ""

until input == "quit"
  print "コマンドをインプットしてください ('quit' でターミネート): "
  input = gets.chomp
  puts "あなたのインプット: #{input}" unless input == "quit"
end

puts "プログラムをエグジットしています。"

このコードのビヘイビア(振る舞い)は while ループのバージョンと完全に一致しますが、ここでのロジックは「ユーザーが "quit" をインプットするまでループが継続する」というものになります。

3. while と until の使い分け

whileuntil ループはどちらも類似のタスクをコンプリートできます。どちらを選択するかは、通常、コードのリーダビリティおよびプログラムの特定のロジックに依存します。

  • while を使用するケース: コンディションが true である時にコードブロックをエグゼキュートしたい場合。
  • until を使用するケース: コンディションが true になるまでコードブロックをエグゼキュートしたい場合。

総じて、コードの意図をより容易に理解でき、推論しやすいループのストラクチャーを選択することがベストプラクティスです。

4. ループコントロール・ステートメント:break と next

breaknext については後続の章で詳細に解説しますが、これらは whileuntil ループとコンバインして頻繁に使用されるため、ここで簡潔にイントロダクションしておく必要があります。

  • break: ループのコンディションに関わらず、即座にループをエグジット(脱出)します。
  • next: 現在のイテレーションの残りの部分をスキップし、直接ループの次のイテレーションへと進みます。

以下は、while ループ内で break を使用するクイックなサンプルです:

counter = 1

while true # これは通常、無限ループになります
  puts counter
  counter += 1
  break if counter > 5 # counter が 5 を超えた場合、ループをエグジットする
end

puts "ループが終了しました!"

このサンプルにおいて、while ループは無期限にランするようにセットアップされています(while true)。しかし、break ステートメントにより、counter が 5 を超えた時点でループがセキュアにエグジットされることが保証されています。