Ruby's redo, retry and next keywords
Thijs Cadier
Posted on June 5, 2018
We've talked about the retry
keyword while discussing retrying after exceptions. Its little-known counterpart redo
works similarly, but re-runs loop iterations instead of whole blocks.
The redo
keyword
As we learned in the previous Academy article, retry
lets you retry a piece of code in a block:
begin
puts "Iteration"
raise
rescue
retry
end
This example prints the word "Iteration" to the console before raising an exception. The rescue blocks executes, which calls retry
and starts the block again from the beginning. This results in our program endlessly printing Iteration
. The redo
keyword lets you achieve a similar effect when using loops. This is useful in situations where you need to retry while iterating for example.
10.times do |i|
puts "Iteration #{i}"
redo if i > 2
end
This will print:
$ ruby redo.rb
Iteration 0
Iteration 1
Iteration 2
Iteration 3
Iteration 3
Iteration 3
...
Notice how the iteration count stays the same? It will step back execution to the start of the loop. This variant of the code using retry
will print the exact same output:
10.times do |i|
begin
puts "Iteration #{i}"
raise if i > 2
rescue
retry
end
end
You can use redo
to implement retrying in a loop. In the next example we have a queue of jobs. They either return :success
or :failure
. We keep re-running the same iteration of the loop until the job succeeds.
[job_1, job_2, job_3, job_4].each do |job|
redo unless job.call == :success
end
Ruby 1.8
The behavior of retry
and redo
changed between Ruby 1.8 and 1.9. They used to restart the loop's iteration, but both in a different way. From 1.9, retry
only works with a begin
/rescue
block and redo
only works within loops.
The next
keyword
If you want to move to the next iteration of the loop, as opposed to moving back to the start of the current one, you can use next
.
10.times do |i|
puts "Iteration #{i}"
next if i > 2
puts "Iteration done"
end
This will print:
$ ruby next.rb
Iteration 0
Iteration done
Iteration 1
Iteration done
Iteration 2
Iteration done
Iteration 3
Iteration 4
...
See how the iteration counter keeps incrementing? In most cases using next
is what you want. Look at redo
if you need a loop that runs an exact number of times or needs error handling when iterating over an array.
We hope you learned something new about redoing iterations in loops and would love to know what you thought of this article (or any of the other ones in the AppSignal Academy series). Please don't hesitate to let us know in the comments what you think, or if you have any Ruby subjects you'd like to learn more about.
Posted on June 5, 2018
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.