Yield!

The yield statement provides a more in-depth look at what happens when enumerators like #each and #collect are used. These methods are used on arrays and iterate through the collection, applying code contained in the block to each element.

Yield is especially powerful because it can take parameters and pass in data as an argument to the code in the block to execute it. To call a method with a yield statement that takes parameters, the method is invoked with an argument and a block that includes the code we want to apply to each yielded value that is passed in.

An example:

1
2
3
4
5
6
7
8
9
10
11
12
def animals(array)
  i = 0
  until i >= array.length
    yield (array[i])
    i += 1
  end
  array
end

animals(['dog', 'cat', 'bear', 'tiger']) do |x| 
  puts "I have a #{x} in my backyard."
end
1
2
3
4
5
> I have a dog in my backyard.
> I have a cat in my backyard.
> I have a bear in my backyard.
> I have a tiger in my backyard.
=> ["dog", "cat", "bear", "tiger"]

We have the #animals array that will iterate over the collection using  an until loop and a yield statement. This method is called on line 10, passing in an argument with the array [‘dog’, ‘cat’, ‘bear’, ‘tiger’]. Notice, a block is also passed in with it:

{ |x| puts "I have a #{x} in my backyard." }

When the method is invoked, the array will be passed into the until loop as it arrives at line 4, the yield statement: yield (array[i]). The control flow will go from line 4 to line 11, as the yield statement will take each element of the array and pass it into the block that was originally called with the #animals method. Then, the control flow returns to line 5, as the iteration increases by one element.

An until (or while) loop will always return nil, so in order to return the original array, we include it on line 7. Of course, if you want to return a modified array, an empty array must first be created and the iterations must be pushed into this modified array and returned on the last line.

Useful!