0 points
Submitted by Anu
over 7 years

# I don't really understand what is this yield

I got the exercise correctly and my code is as below

``````def double(n)
yield n

end

double(2) do |n|
n*=2
end``````

But my question is I don’t really understand why need to do like this when there is a more easier way like the following

``````def double(n)
n*=2

end

double(2)``````

Can anyone explain why do we need to use yield?

In the very simple example you presented, `yield` doesn’t make much sense indeed. But the mechanism of yielding to blocks in Ruby provides the programmer with a great flexibility. A block is simply a chunk of code, and `yield` allows you to “inject” that code at some place into a function. So if you want your function to work in a slightly different way, you don’t have to write a new function, instead you can reuse the one you already have, but give it a different block.

For example, consider a function that will print the members of an Array, but number them, like this: if you give it `["apple","banana"]`, it should print

``````1. apple
2. banana``````

Easy enough, right? There are several ways to do this, but I’ll just use `each` and a counter. Instead of incrementing the counter via `+= 1`, I’d like to use the `next` method (you’ll see why in a moment). Here’s how the `next` method works: `3.next` equals `4`, `99.next` is `100` and so on. So here’s our method (without `yield`):

``````def print_list(array, first = 1)
counter = first
array.each do |item|
puts "#{counter}. #{item}"
counter = counter.next
end
end``````

Now when we call `print_list(["Ruby", "Python", "C"])`, it’ll print

``````1. Ruby
2. Python
3. C``````

The second parameter `first` is optional (it defaults to `1` because of the `first=1` above) and it tells our function where to start counting:

``print_list(["a","b","c"], 99)``

will print

``````99. a
100. b
101. c``````

Because I chose `next` over `+= 1` to increment the counter, and because Ruby is really awesome, we can use strings instead of numbers to label the list items: `"A".next` is `"B"`, and so forth. Thus

``````print_list(["Ruby", "Python", "C"], "X")

# will print:

X. Ruby
Y. Python
Z. C``````

Great, right? But what if we wanted a different format for the item labels? Say, `(1)`, `(2)`, `(3)` instead of `1.`, `2.`, `3.`? Our function does the formatting in this line:

``puts "#{counter}. #{item}"``

So instead of having two (almost identical) functions – one for `1. 2.` and one for `(1) (2)` (and so on, one for every possible idea), we’re going to export that formatting thing into a block, and have just a `yield` inside the function:

``````# function print_list, line 4:
puts "#{yield counter} #{item}"``````

Now we can have a block handle the formatting:

``````print_list( [1,2,3], 23 ) { |n| "<#{n}>"}

# produces:

<23> 1
<24> 2
<25> 3``````

Now I hope you see how this `yield` adds flexibility to your method. You can, for instance, have something like this:

``````print_list( ["alpha","beta","gamma"], 5 ) do |n|
"[#{100*n}]:"
end``````

This prints… can you guess what it prints? Try to figure it out, then go here to find out the answer and see more examples.

3117 points
Submitted by Alex J
over 7 years

Anu over 7 years

Thanks a lot Alex. I got how yield works from your explanation. Though I didn’t understand some of the codes you given for the different printing formats.

I don’t understand this part:

# function print_list, line 4:

puts “#{yield counter} #{item}”

I do understand what the “yield” does in there, but where did the # function print_list, line 4:” come from? Very confused

Alex J over 7 years

It’s simply the fourth line in the function I defined above… Just replace the fragment `puts "#{counter}. #{item}"` with the fragment `puts "#{yield counter} #{item}"` inside the definition of the print_list function.

Alex J over 7 years

Brian W over 7 years

I would just like to say that if an example “doesn’t make much sense” as you point out, it’s probably not a good idea to use it to introduce new concepts in a beginner’s tutorial.

Snarik over 7 years

Holy shit that was a great explanation. I wish I could mail you a medal or at least a cuddle or something.

Thank you! This is great :)

Great explanation! Thanks a lot!

Danny Sullivan almost 7 years

Thank you for this explanation. For me, a lot of these exercises lack context, it is hard to see exactly how and why you would use whatever it is you are learning. Your explanation cleared that up in the first two sentences. I wish Codecademy would start to incorporate more examples of why you would use something instead of just giving an exercise.

Oleg Joel Malinovsky almost 7 years

Oooohh… this this is what it does. THANKS!

znapper over 6 years

Thanks Alex!! Great Explanation!

Kyler Chua over 6 years

Thank you Danny for raising the question. Was lost as well. Alex thank you for spending time explaining, appreciate it! XD

Anne N over 6 years

Thank you so much for explaining this! I was so confused as to how yield was applicable when other methods work just as well for this particular assignment. Much appreciated!

Alex over 6 years

Thank you!!

Mantas Jonušas over 6 years

good explanation. but why don’t do formating in the puts line: puts “<#{counter}> #{item}” and etc. and do things as simple as possible

Thank you much!!

Todd Mathews over 6 years

Very good explanation. Thanks I understand it now.

Bekah over 6 years

THANK YOU.

bumblebeezel over 6 years

Godsend

Useful, nice to have a concrete example of why we might do something, instead of just how.

Yeah I agree with Toby. Thank you both.

Thank you for the explanation! But I am wondering how does ruby know that ‘n’ refers to the second parameter and not the first in ‘print_list( [1,2,3], 23 ) { |n| “<#{n}>”}’

Ti Pro over 5 years

I think because n is a number, a symbol not is an array. Beside that, yield make you have a prametter so ruby will follow this parameter to do with block

Jenn Goble over 5 years

Thanks for such a helpful explanation!

Spencer Romberg over 5 years

Well done. Have you ever considered going into computer science for teaching?

Michael Du over 5 years

I know this post is 2 years old, but hoping you’re still around for questions: Why do we need “counter” in your example? It works perfectly fine using “first” directly within the block.

Nitya Narayan over 5 years

to retain value of first.counter value is incremented…. ‘first’ value remains the same

BlackFiresong over 5 years

Amazing! Thank you so much. I was really mystified by the whole yield thing. Thanks for taking the time to write such a detailed explanation. If you’re not a teacher by profession, you should be!

this explanation also helped em alot understand the yield thingy. thanks a lot @Alex

946 points
Submitted by siaw23™
over 7 years

Alex J over 7 years