Search code examples
rubywhile-loopredo

Ruby's redo method vs while loop


I was reading this question and it got me thinking why one would want to use a while loop when the redo method could be used instead. I can't find any differentiation between the two. I know that the redo method will rerun the block of code, and that while loops will rerun the block of code as long as the conditional is true. Can someone give an example of why you'd want to use one or the other?


Solution

  • The redo command restarts the current iteration of a loop (without checking termination conditions in while or advancing iterators in for, for example), you still need a loop of some description (such as a while loop).

    That's evidenced by the answer you link to, which contains:

    nums = Array.new(5){[rand(1..9), rand(1..9)]}
    nums.each do |num1, num2|
      print "What is #{num1} + #{num2}: "
      redo unless gets.to_i == num1 + num2
    end
    

    The .each provides the looping structure there and all the redo does is restart that loop (without advancing to the next nums element) if you get the answer wrong.

    Now you could actually use a while loop there as the controlling loop, advancing to the next one only if you get it right:

    nums = Array.new(5){[rand(1..9), rand(1..9)]}
    index = 0
    while index < 6 do
        num1 = nums[index][0]
        num2 = nums[index][1]
        print "What is #{num1} + #{num2}: "
        if gets.to_i == num1 + num2 then
            index = index + 1
        end
    end
    

    or within the .each itself without redo:

    nums = Array.new(5){[rand(1..9), rand(1..9)]}
    nums.each do |num1, num2|
        answer = num1 + num2 + 1
        while answer != num1 + num2 do
            print "What is #{num1} + #{num2}: "
            answer = gets.to_i
        end
    end
    

    but neither of them are as elegant as the redo solution, which provides a more expressive way of controlling loops, an extension to the usual control you see in other languages, such as continue or break.