例外後の再試行について説明する際に、retry
キーワードについて話しました。 そのあまり知られていない対応するキーワード redo
も同様に機能するが、ブロック全体ではなくループの繰り返しを再実行する。
The redo keyword
以前の Academy の記事で学んだように、retry
はブロック内のコードの一部を再試行することができます:
1 2 3 4 5 6 |
begin puts "Iteration" raise rescue retry end |
このサンプルは例外発生前に「Iteration」と表示されコンソールへ出力されます。 レスキューブロックが実行され、retry
が呼び出され、ブロックが最初から再び開始される。 この結果、プログラムは延々とIteration
を表示することになる。 redo
キーワードを使用すると、ループを使用するときに同様の効果を得ることができます。 これは、例えば反復処理中に再試行する必要があるような場合に便利です。
1 2 3 4 |
10.times do |i| puts "Iteration #{i}" redo if i > 2 end |
これはプリントされます。
1 2 3 4 5 6 7 8 |
$ ruby redo.rb Iteration 0 Iteration 1 Iteration 2 Iteration 3 Iteration 3 Iteration 3 ... |
繰り返し数が同じであることに注意してください? これは、ループの開始点まで実行をステップバックすることになる。
1 2 3 4 5 6 7 8 |
10.times do |i| begin puts "Iteration #{i}" raise if i > 2 rescue retry end end |
ループで再試行を実装するのに redo
を使用することができます。 次の例では、ジョブのキューがある。 それらは :success
か :failure
を返す。 ジョブが成功するまで、ループの同じ繰り返しを実行し続けます。
1 2 3 |
.each do |job| redo unless job.call == :success end |
retry
と redo
は Ruby 1.8 から 1.9 で動きが変わってきています。 以前はループの繰り返しを再開していましたが、どちらも異なる方法で再開しています。 1.9からは、retry
はbegin
/rescue
ブロックでのみ動作し、redo
はループ内でのみ動作するようになりました。
nextキーワード
現在のループの開始点に戻るのではなく、次の反復に移りたい場合は、next
を使用することができます。
1 2 3 4 5 |
10.times do |i| puts "Iteration #{i}" next if i > 2 puts "Iteration done" end |
これで表示されます。
1 2 3 4 5 6 7 8 9 10 |
$ ruby next.rb Iteration 0 Iteration done Iteration 1 Iteration done Iteration 2 Iteration done Iteration 3 Iteration 4 ... |
反復カウンターがいかに増加し続けるかわかるでしょうか。 ほとんどの場合、next
を使用することが望ましいです。 ループの反復を正確に実行する必要がある場合、または配列上で反復するときにエラー処理が必要な場合は、redo
を参照してください。
ループの反復のやり直しについて何か新しいことを学んでいただければと思います。 この記事の感想や、もっと学びたいRubyのテーマがあれば、遠慮なくお知らせください
。