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