1
0

Ruby:多重ループを抜ける大域脱出とは

Last updated at Posted at 2024-08-01

※この記事は初学者が自分なりにまとめたものになります。

目次

はじめに

今日は、Rubyにおいて2重3重に重なったループを一撃で抜ける方法を調べてみました!

大域脱出とは

この何重にも重なったループを抜け出す処理を"大域脱出”と言います。

<代表的な大域脱出方法2選>

以下は、Rubyの大域脱出の方法で代表的なもの2つです。

1. return

メソッドやブロックの実行を終了し、呼び出し元に制御を戻します。メソッドの中で使われることが多いです。

2. throw catch

特定のスコープから大域脱出するための方法で、throwは指定されたシンボルを投げ、対応するcatchブロックに制御を戻します。複雑な制御フローが必要な場合に使われます。

どちらの方法でも多重ループから抜け出すことができるのですが、明確な違いがあります。

メソッド内で多重ループの処理があって、そこから大域脱出した時に同メソッド内の後の処理を実行するのかどうかという点です。

実際のコードで見てもらった方が早いと思います。

return

このコードでは、2つの範囲オブジェクト (1..3) を使って各ループが1から3までの値を順に取り、全ての組み合わせを総当たりで処理します。
特定の条件が満たされた場合に、returnを使ってメソッド全体から抜け出します
returnに行く条件は、if文で2.2の組み合わせの時としています。
そのため、returnされる2.2以降の2.3, 3.1, …といった組み合わせは出力されません。

def nested_loops_with_return
  (1..3).each do |i|
    (1..3).each do |j|
      if i == 2 && j == 2
        # 内側のループからメソッド全体を抜け出す
        return "Exited with return"
      end
      puts "i: #{i}, j: #{j}"
    end
  end
  "This line will not be executed"
end

puts nested_loops_with_return
# Output:
# i: 1, j: 1
# i: 1, j: 2
# i: 1, j: 3
# i: 2, j: 1
# Exited with return

throw catch

このコードも、2つの範囲オブジェクト (1..3) を使って各ループは1から3までの値を順に取り、全ての組み合わせを総当たりで処理します。
特定の条件が満たされた場合に、throwを使ってcatchブロックから抜け出します
catchブロックから抜け出すのみなので、メソッド内のその後の処理を実行することができます。

throwは名前のとおり、指定のシンボルを投げます。

そして、対応するcatchブロックに制御を戻します。

今回、指定のシンボルは:exit_pointとしました。

def nested_loops_with_throw_catch
  result = catch(:exit_point) do
    (1..3).each do |i|
      (1..3).each do |j|
        if i == 2 && j == 2
          # 内側のループから外側のループ全体を抜け出す
          throw :exit_point, "Exited with throw and catch"
        end
        puts "i: #{i}, j: #{j}"
      end
    end
  end
  # 外側のループ全体を抜け出した後の処理
  puts "This line is inside the method after throw"
  puts result
end

nested_loops_with_throw_catch
# Output:
# i: 1, j: 1
# i: 1, j: 2
# i: 1, j: 3
# i: 2, j: 1
# This line is inside the method after throw
# Exited with throw and catch

まとめ

メソッドから抜け出すのがreturn

ブロックから抜け出すのがthrow catchです。

使い分けのポイント

  1. メソッド全体を終了させたい場合:
  • returnを使用します。メソッドの途中で処理を終了し、呼び出し元に制御を戻したい場合に適しています。
  1. ネストされたループや特定のスコープから抜け出したい場合:
  • throw catchを使用します。特定の条件が満たされた場合に、ネストされたループや複雑な制御フローから抜け出し、その後の処理を続けたい場合に適しています。

3.後続の処理が必要かどうか:

  • returnはメソッド全体を終了させるため、後続の処理は実行されません。
  • throw catchは特定のスコープから抜け出すため、後続の処理を実行することができます。

状況に応じて使い分けましょう!

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0