46

The Yield Keyword in Ruby

 5 years ago
source link: https://www.tuicool.com/articles/hit/qYNFfeY
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
uMBbqeJ.png!web

My Ruby :love_letter: newsletter :love_letter: is available here ! Feel free to subscribe ! :rocket:

The Yield Keyword in Ruby

In this article, we’re going to explore the following topics:

Enumerable#map

The yield keyword — in association with a block — allows to pass a set of additional instructions during a method invocation.

This mechanism allows you to customise a method depending on your needs.

What’s a block ?

A block is part of the Ruby method syntax.

This means that when a block is recognised by the Ruby parser then it’ll be associated to theinvoked method and literally replaces the yield s in the method

produces

one yield
multiple yields
multiple yields

The code inside the block will literally replace the yield keyword in the method definition.

Now, what happens if we don’t pass a block during method invocation for a method that includes a yield ?

block_given?

When yield is called in a method then the method requires a block. Otherwise, a LocalJumpError is raised

So, how to make the block optional ? The answer is by using the Kernel#block_given? method

Arguments

yield can take a list of arguments that will be available for the block

Here, the block takes the arguments |hello, world| that are provided by the yield inside the yield_with_arguments method.

Return value

It’s possible to get the return value of a block by simply assigning the return value of a yield to a variable

The hello_world variable get the "Hello World!" returned by the block and display it by using puts .

Array#my_map

Now that we’ve made an overview of yield and blocks, let’s try to recap the important notions by implementing an example.

The Enumerable#map method allows you to iterate over a list of objects and manipulate each of them. Then it’ll return a new list that contains all the manipulated objects.

$> array = [1, 2, 3]
=> [1, 2, 3]
$> array.map {|n| n + 2}
=> [3, 4, 5]
$> array
=> [1, 2, 3]

In the above example, we assign [1, 2, 3] to the array variable.

Then we call the array.map {|n| n + 2} that adds 2 to each element of the array . a new array that contains [3, 4, 5] is returned by the map method.

Finally, we see that the initial array didn’t change.

Now, let’s try to implement our own version of Enumerable#map directly on the Array class

$> array = [1, 2, 3]
=> [1, 2, 3]
$> array.my_map {|n| n + 2}
=> [3, 4, 5]
$> array
=> [1, 2, 3]

Our custom method has the same behaviour as the Enumerable#map method.

That’s great ! Now let’s dive in the code.

1- we create a temporary Array named ary . This variable will contain the return value of our method.

2- we iterate over the receiver Array by using self.each .

3- for each element, we call yield(elem) — where elem is the current element of the iteration. Then, we store the return value of the yield(elem) in the ary variable.

4- we return ary .

Now, what happens if we don’t pass a block to our Array#my_map method?

$> array.my_map
LocalJumpError (no block given (yield))

As you probably expected, an error is raised.

But fortunately, we’ve already fixed this issue in the previous sections.

So let’s reuse the Kernel#block_given? method to enhance our Array#my_map method

$> array.my_map
=> [1, 2, 3]

If there is no block passed to the method then we force the method to return a copy of the receiver array.

Voilà !

Thank you for taking the time to read this post :-)

Feel free to :clap: and share this article if it has been useful for you.

My Ruby :love_letter: newsletter :love_letter: is available here ! Feel free to subscribe ! :rocket:

Here is a link to my last article: A matter of Attributes .


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK