例外後の再試行について説明する際に、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 
Ruby 1.8

retryredo は Ruby 1.8 から 1.9 で動きが変わってきています。 以前はループの繰り返しを再開していましたが、どちらも異なる方法で再開しています。 1.9からは、retrybegin/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のテーマがあれば、遠慮なくお知らせください

コメントを残す

メールアドレスが公開されることはありません。