Skip to Content
Delete Icon
This forum is now read-only. Please use our new forums at discuss.codecademy.com.
0 points
Submitted by Anu
7 years ago

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?

Answer 51c75f68631fe903b4001e5d

215 votes

Permalink

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
7 years ago

29 comments

Anu 7 years ago

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 7 years ago

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 7 years ago

see my answer below

Brian W 7 years ago

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 7 years ago

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

Anna Baik 7 years ago

Thank you! This is great :)

alibedde 7 years ago

Great explanation! Thanks a lot!

Danny Sullivan 7 years ago

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.

Oooohh… this this is what it does. THANKS!

znapper 7 years ago

Thanks Alex!! Great Explanation!

Kyler Chua 7 years ago

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

Anne N 7 years ago

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 6 years ago

Thank you!!

Mantas Jonušas 6 years ago

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 6 years ago

Very good explanation. Thanks I understand it now.

Bekah 6 years ago

THANK YOU.

bumblebeezel 6 years ago

Godsend

Toby 6 years ago

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

Leah Suter 6 years ago

Yeah I agree with Toby. Thank you both.

NYJY85 6 years ago

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 5 years ago

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 5 years ago

Thanks for such a helpful explanation!

Spencer Romberg 5 years ago

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

Michael Du 5 years ago

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 5 years ago

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

BlackFiresong 5 years ago

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!

Answer 51caff9352f8633982007a5c

0 votes

Permalink

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

946 points
Submitted by siaw23™
7 years ago

1 comments

Alex J 7 years ago

Glad I could help

Answer 53c9cd74631fe9afa9000054

0 votes

Permalink

Great explanation, thanks

1084 points
Submitted by Ray Rai
6 years ago