最も内側のループからの脱出にはbreakを用います。一方、いくつもネストした処理から一気に抜け出したい時は大域脱出を用います。
任意の処理からの脱出
大域脱出の手段としてcatch・throwが提供されています。いくつもネストした処理から一気に抜けだしたいときにはthrowを呼び出します。catch・throwを用いて、ネストした繰り返し処理から脱出してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
catch :triple_loop do loop do puts 'one' loop do puts 'two' loop do puts 'three' throw :triple_loop end end end end # "one" "two" "three"と順番に表示 |
loopは無限ループするメソッドですが、throwを呼び出すことによって最初のループで脱出できています。
catchに渡したブロックの中でthrowを呼び出すと、catchの呼び出し元に戻ることができます。catchには、throwする際にcatchを指定するための名前をシンボルまたは文字列で指定します。throwを呼び出すと、指定された名前のcatchのブロックを中断し、catchの呼び出し元に戻ります。
catchは以下のようにネストさせることができます。throwに渡す名前によって、どのcatchのブロックを中断するかが変わります。
1 2 3 4 5 |
catch :entire do catch :process do throw :entire # :entireのブロックを中断する end end |
throwの第二引数にはcatchの戻り値を渡すことができます。第二引数が渡されなかった場合、catchはnilを返します。
1 2 3 |
catch(:foo){ throw :foo, 'returned value' } # => 'returened value' |