PerlerのRuby日記

Rubyとか

多重ループからの脱出

単純なループやイテレータは、breakで脱出できる。

num = [1,2,3,4,5,6,7,8,9,10]
num.each do |i|
  break if i > 5
  puts i
end
puts "----------------------"
for i in num
  break if i > 5
  puts i
end
1
2
3
4
5
----------------------
1
2
3
4
5

ただしこれは最も内側のループに限る。

num = [1,2,3,4,5]
num.each do |i|
  num.each do |j|
    break if j > 1
    puts j
  end
end
1    # 5回外側のループが実行される
1
1
1
1

Perlだとループにラベル貼って、そこに飛ぶ!という感じ。

my @num = 1 .. 5;
OUT: for my $i (@num) {
  IN: for my $j (@num) {
    last OUT if $i > 1;
    say $i;
  }
}

Rubyだと少し工夫が必要で、外側をcatchで囲ってシンボルを指定して、throwでそのシンボルが投げられたらcatchがキャッチ!となるみたい。

num = [1,2,3,4,5]

catch(:out) do
  num.each do |i|
    num.each do |j|
      throw :out if j > 1
      puts j
    end
  end
end  
1    # throw で catch の範囲を抜けた

この辺の制御がオブジェクト指向で煩雑になるってことなのかな。

その分、逆に必要性は薄れてるともいえるか。