When and Why use Loop Do Construct in Ruby

Adding up to the previous answers,

The "loop do" construct also offers a cleaner syntax when working with external iterators, e.g

No "loop do"

my_iterator = (1..9).each
begin
  while(true)
    puts my_iterator.next
  end
rescue StopIteration => e
  puts e
end

And now with "loop do" this would become

my_iterator = (1..9).each
loop do
  puts my_iterator.next
end

And the exception is handled for you. It also allows you to loop through two collections at the same time and as soon as one of them runs out of elements the loop exits gracefully,

iterator = (1..9).each
iterator_two = (1..5).each

loop do
  puts iterator.next
  puts iterator_two.next
end

It will print: 1,1,2,2,3,3,4,4,5,5,6.

More info on it at: ruby-docs.org


In a language without loop, you might use a while construct like:

while( true ) {
  # Do stuff until you detect it is done
  if (done) break;
}

The point of it is that you start the loop without knowing how many of iterations to perform (or it is hard to calculate in advance), but it is easy to detect when the loop should end. In addition, for a particular case you might find the equivalent while (! done) { # do stuff } syntax clumsy, because the done condition can happen halfway through the loop, or in multiple places.

Ruby's loop is basically the same thing as the while( true ) - in fact you can use while( true ) almost interchangeably with it.

In the given example, there are following points of return within each iteration:

if (left >= 0) && (arr[left] > arr[idx])
  return left   # <-- HERE
elsif (right < arr.length) && (arr[right] > arr[idx])
  return right  # <-- HERE
elsif (left < 0) && (right >= arr.length)
  return nil    # <-- HERE
end 

There is also an implied "else continue looping" here, if no end conditions are met.

These multiple possible exit points are presumably why the author chose the loop construct, although there are many ways of solving this problem in practice with Ruby. The given solution code is not necessarily superior to all other possibilities.


Using the loop do construct allows you to break on a conditional.

for instance:

i=0
loop do
  i+=1
  print "#{i} "
  break if i==10
end 

You would want to use this when you know the number of elements that will be processed, similar to that of the for each loop