大域脱出(ruby, java)

rubyには大域脱出という機能があることを思い出したのでメモ。
通常のbreakだと複数のループからは抜けられないが、大域脱出を使えば任意のラベルの箇所まで脱出が可能。goto文がない言語だと大域脱出 or 例外処理を使う必要がある。
以下rubyの例。

puts "=== normal break ==="
0.upto(3) do |x|
  0.upto(3) do |y|
    puts "x = #{x}, y = #{y}"
    break if y == 1
  end
end

puts "=== global exit ==="

catch :label do 
  0.upto(3) do |x|
    0.upto(3) do |y|
      puts "x = #{x}, y = #{y}"
      throw :label if y == 1
    end
  end
end

アウトプットは以下。

=== normal break ===
x = 0, y = 0
x = 0, y = 1
x = 1, y = 0
x = 1, y = 1
x = 2, y = 0
x = 2, y = 1
x = 3, y = 0
x = 3, y = 1
=== global exit ===
x = 0, y = 0
x = 0, y = 1

以下javaの例。

class A {
  public static void main(String args[]){
    System.out.println("=== normal break ===");
    for(int x = 0; x < 4;x++) {
      for(int y = 0;y < 4;y++){
        System.out.println("x = " + x + ", y = " + y);
        if(y == 1){ break; }
      }
    }

    System.out.println("=== global exit ===");
    label:
    for(int x = 0; x < 4;x++) {
      for(int y = 0;y < 4;y++){
        System.out.println("x = " + x + ", y = " + y);
        if(y == 1){ break label; }
      }
    }
  }
}

アウトプットは以下。

=== normal break ===
x = 0, y = 0
x = 0, y = 1
x = 1, y = 0
x = 1, y = 1
x = 2, y = 0
x = 2, y = 1
x = 3, y = 0
x = 3, y = 1
=== global exit ===
x = 0, y = 0
x = 0, y = 1