KEEP K.I.S.S.

tk's blog

Yield in Ruby

tk posted @ May 09, 2011 03:20:22 AM in Ruby with tags ruby , 2004 阅读

# 这是一篇转载的文章,From http://fairleads.blogspot.com/2007/06/ruby-yield.html

Yield 是 Ruby 里面一个很独特的关键字,这篇文章可以帮助你很好的理解她。


 

TUESDAY, JUNE 5, 2007


Ruby Yield

 

 

Yield is one of the most powerful concepts implemented in the Ruby programming language. Yield lets you branch from within a method and execute some external code, then return to the original code in the first method.
 

What's so special about yield in Ruby? You could get the same branch and return flow by just executing a method call in java, or a function call in C. 
 

Heck, COBOL's PERFORM verb implements branch and return behavior. So what's up with yield?
 

Well, the behavior of what you branch to is set in stone with all those other techniques, but is undetermined until coded in RubyYield is kind of like a place holder that says "I'm going to branch off and do something here, but I don't know what I'm going to do yet".
 

Maybe some examples will help make it more clear. Here is a Ruby method with some yields coded in it, then the code to invoke the method and the block of code to invoke when the yield is encountered:

 

def block1
 puts "Start of block1..."
 yield
 yield
 puts "End of block1."
end

block1 {puts "yielding..."}

Running this code would produce the following output:

 

Start of block1...
yielding...
yielding...
End of block1.

So block1 executes it's first line and prints "Start of block1...", then it executes the yields which branch to the block of code outside block1 but associated with it at run time, then comes back and prints "End of block1."

OK that's, fine but isn't that functionally the same as the following code:

 

def block2
 puts "Start of block2..."
 put_it("in put_it called method...")
 put_it("still in put_it called method...")
 puts "End of block2."
end

def put_it(text)
 puts text
end

block2

Running this second set of code produces the following:

 

Start of block2...
in put_it called method...
still in put_it called method...
End of block2.

For the most part, these are pretty much the same. However without having to redefine any methods I could immediately execute the block1 method with a different block associated with it. The yield would branch and execute this newly associated logic:

 

block1 {require 'time' 
 puts Time.now.httpdate}

This produces the output:

 

Start of block1...
Tue, 05 Jun 2007 19:20:35 GMT
Tue, 05 Jun 2007 19:20:35 GMT
End of block1.

The hard coded function call in block2 forever ties the branching logic to the put_it function. To get different behavior you would need to either change the function call in block2 to call a different function, or change the behavior of the function put_it. This second way is brittle because it could break code elsewhere that calls put_it. The first is cumbersome and possibly brittle.

Ruby's yield is a wonderful construct.

What about when you don't want to branch, but want the other functionality in the block1 code to be executed? Can you just run the code without the associated block?

Let's see what happens. Running block1 without an attached block for the yield to associate to:

block1

This produces the result:

Start of block1...
LocalJumpError: no block given
from :3:in 'block1'
from :7
from :0

We get a 'no block given' error at line 3 in method 'block1'. Line 3 is our first yield in the block1 method. 

What to do?

We can wrap the yield in an if statement and check for the presence of a block using the block_given? conditional. It returns true if a block was given with the method call, or false if not.

For this example I'll use a slightly more idiomatic way of checking for the presence of a block in ruby:

 

def block3
 puts "Start of block3..."
 yield if block_given?
 puts "End of block3."
end

now if we run the code with a block:

 

block3 { puts "yielding" }

or without:

block3

It works both times producing:

Start of block3...
yielding...
End of block3.

and

Start of block3...
End of block3.

This will make your methods less brittle and more agile. 

Ruby's yield is worth getting to know. You can learn more here and here. Many of Ruby's built in methods contain yields that allow you to associate blocks with them producing added functionality at run time.

 

 

buy clenbuterol onli 说:
Mar 10, 2023 03:52:18 AM

I truly like you're composing style, incredible data, thankyou for posting. buy clenbuterol online

The Lord of the Ring 说:
Apr 26, 2023 01:44:10 AM

It is perfect time to make some plans for the future and it is time to be happy. I've read this post and if I could I desire to suggest you some interesting things or suggestions. Perhaps you could write next articles referring to this article. I want to read more things about it! The Lord of the Rings: The Rings of Power Bronwyn Cape

KERASSENTIALS REVIEW 说:
Jul 10, 2023 09:41:29 PM

I see some amazingly important and kept up to length of your strength searching for in your on the site KERASSENTIALS REVIEWS

41215663 说:
Jul 23, 2023 06:14:24 AM

It was a very good post indeed. I thoroughly enjoyed reading it in my lunch time. Will surely come and visit this blog more often. Thanks for sharing. 41215663

GLUCOFREEZE 说:
Jul 24, 2023 11:28:29 PM

The next time I read a blog, I hope that it doesnt disappoint me as much as this one. I mean, I know it was my choice to read, but I actually thought you have something interesting to say. All I hear is a bunch of whining about something that you could fix if you werent too busy looking for attention. GLUCOFREEZE

Matt Davies 说:
Aug 28, 2023 05:00:31 AM

Here at this site really the fastidious material collection so that everybody can enjoy a lot. Matt Davies

tech 说:
Dec 05, 2023 04:57:00 AM

I recently came across your article and have been reading along. I want to express my admiration of your writing skill and ability to make readers read from the beginning to the end. I would like to read newer posts and to share my thoughts with you. UFABETโปรโมชั่นเว็บบอล

boardmodelpaper.com 说:
Jan 25, 2024 10:58:06 PM

Board Model Papers 2024 Download with Suggestions for 10th Class Textbooks 2024 Pdf Download and SSLC New Syllabus Sample Question Paper 2024 and different types of model papers boardmodelpaper.com and question papers for following the website and Arts, Science, Commerce Stream Subject Wise Solved Question Bank for Hindi & English Medium Students with Exam Pattern & Blueprint and subject Wise with 11th & 12th Question Bank 2024 for General & Vocational Course Languages & Subjects Important Question for the above link.


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter