Iterators are a crucial component of the programming world. Ruby make iterators easy to use and read.

Iterating over a simple array may look something like this:

> plain_numbers = [ 2 , 3 , 4 ] => squared_values = [] > plain_numbers . each do | n | > squared_values << n ** 2 > end > squared_values => [ 4 , 9 , 16 ]

This snippet of code should be simple enough to understand. First, we created an array called plain_numbers . We also created an empty array named squared_values .

The next section of code is called a block in Ruby. The each method signifies that we'll be going through each element in the object (in this case it's the plain_numbers array) and interacting with it. The element gets passed in to the block of code as the n variable. We take this n variable, square it, and then add it to the squared_values array. Simple enough.

Ruby comes with a bunch of iterators built-in, like each , times , upto, and each_index`. These iterators are simple but powerful and you'll see them being used all over Ruby code.

Rolling your own iterator

Sometimes a situation might arise when the built-in Ruby iterators just won't cut it. What then? Luckily, Ruby makes it pretty easy to write your own custom iterator.

Here is a simple case of writing our own custom iterator:

def simple_block puts "This is in the method" yield puts "This is still in the method" yield end simple_block { puts "This is in the block" }

Would result in:

This is in the method This is in the block This is still in the method This is in the block

As you can see, the block is being invoked by calling the method of the same name, simple_block . When we first call simple_block , the method starts and puts "This is in the method" is called. yield then hands off responsibility to the block (which is denoted by the curly brackets). Once this block is done running, we're back in the original method again. This process happens one more time when yield is called yet again.

When I first encountered the yield statement, I found it incredibly confusing. I still can't claim mastery over it, but simple examples like the one above helped me to better understand it.

Here's another simple example of a custom iterator in use. Let's pretend we're building a game that needs to check whether or not a character's name is valid. For whatever reason, we only want character names that are greater than 3 characters.

character_names = [ 'Jon' , 'Ricky' , 'Andrew' ] def valid_character_checker ( names ) names . each do | name | puts "Is #{ name } a valid charcter?" yield ( name ) end end valid_character_checker ( character_names ) do | name | if name . length > 3 puts "This is a valid character name!" else puts "This is an invalid character name :(" end end

Once again, this example is pretty simple if you work through it step-by-step. It's also pretty verbose and probably not the best example of what real code would look like in the wild.