2.8. Loops

There are different ways of implementing loops in Ruby. The iterator variation is used particularly often in the Rails environment.

while and until

An abstract while loop looks like this:
while expression do
  program
end

Buy the new Rails 5.1 version of this book.

The do that follows the expression is optional. Often you will also see this:
while expression
  program
end
Here is a practical irb example:
$ irb --simple-prompt
>> i = 0
=> 0
>> while i < 3 do
?>   puts i
>>   i = i + 1
>> end
0
1
2
=> nil
>> exit
$
Until loops are built similarly:
until expression
  program
end
Again, here is the corresponding irb example:
$ irb --simple-prompt
>> i = 5
=> 5
>> until i == 0
>>   i = i - 1
>>   puts i
>> end
4
3
2
1
0
=> nil
>> exit
$

Blocks and Iterators

Block and iterator are some of the favorite words of many Ruby programmers. Now I am going to show you why.
In the loop
5.times { |i| puts i }
i is the iterator and puts i is the block.
You can also express the whole thing in the following syntax:
5.times do |i|
  puts i
end

Iterators

Iterators are just a specific type of method. As you probably know, the word iterate means to repeat something. For example, the class Fixnum has the iterator times. Let's see what help ri offers us:
$ ri -T Fixnum.times
Fixnum.times

(from ruby site)
Implementation from Integer
------------------------------------------------------------------------------
  int.times {|i| block }  ->  self
  int.times               ->  an_enumerator
   

------------------------------------------------------------------------------

Iterates block int times, passing in values from zero to int -
1.

If no block is given, an enumerator is returned instead.

  5.times do |i|
    print i, " "
  end

produces:

  0 1 2 3 4


$ 
And it also gives a nice example that we are going to try out in irb:
$ irb --simple-prompt
>> 5.times do |i|
?>   puts i
>> end
0
1
2
3
4
=> 5
>> exit
$
There is also a single-line notation for small blocks:
$ irb --simple-prompt
>> 5.times { |i| puts i }
0
1
2
3
4
=> 5
>> exit
$ 
By the way, an iterator does not necessarily have to pass a variable to the block:
$ irb --simple-prompt
>> 5.times { puts 'example' }
example
example
example
example
example
=> 5
>> exit
$

Blocks

A block is the code that is triggered by an iterator. In the block, you have access to the local variable(s) passed by the iterator.

Method upto

Apart from times there is also the method upto, for easily implementing a loop. ri offers a nice example for this, too:
$ ri -T Fixnum.upto
Fixnum.upto

(from ruby site)
Implementation from Integer
------------------------------------------------------------------------------
  int.upto(limit) {|i| block }  ->  self
  int.upto(limit)               ->  an_enumerator
   

------------------------------------------------------------------------------

Iterates block, passing in integer values from int up to and
including limit.

If no block is given, an enumerator is returned instead.

  5.upto(10) { |i| print i, " " }

produces:

  5 6 7 8 9 10


$

Thank you for your support and the visibility by linking to this website on Twitter and Facebook. That helps a lot!