[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Using yield

Van Dyk, Joe

12/4/2004 12:11:00 AM

I come from a heavy C++ background, discovered Ruby a few months ago and
love it.

I've found that using blocks is a very natural thing. However, I have not
once used 'yield'. I'm sure that there are events when using yield would be
helpful, but I have no clue when it would be appropriate to use.

Thoughts? When do you use the 'yield' statement in code?

Joe


25 Answers

Sam Stephenson

12/4/2004 12:42:00 AM

0

On Sat, 4 Dec 2004 09:32:39 +0900, Joe Van Dyk <joe.vandyk@boeing.com> wrote:
> When do you use the 'yield' statement in code?

When you want to write methods that take blocks.

| def repeatedly_write(times, &block)
| times.times do |i|
| puts yield(i)
| end
| end
|
| repeatedly_write(5) do |i|
| "iteration #{i}"
| end

prints:
iteration 0
iteration 1
iteration 2
iteration 3
iteration 4

In this example, ``yield(i)'' and ``block.call(i)'' are equivalent.

> Joe

Sam


Tim Hunter

12/4/2004 12:48:00 AM

0

Joe Van Dyk wrote:

> I come from a heavy C++ background, discovered Ruby a few months ago and
> love it.
>
> I've found that using blocks is a very natural thing. However, I have not
> once used 'yield'. I'm sure that there are events when using yield would
> be helpful, but I have no clue when it would be appropriate to use.
>
> Thoughts? When do you use the 'yield' statement in code?
>
> Joe

I use it with methods that create resources that need to be cleaned up
after, the way File.open closes the file for you after the block
terminates. If you're coming from C++, think destructors.

Here's an example from RMagick. The Image#view method extracts a rectangle
of pixels from an image and yields to a block (if present). Within the
block you can address the pixels using [i][j] indexes. When the block ends,
if any of the pixels have been modified all the pixels are stored
("sync'd") back to the image. The code looks like this:

def view(x, y, width, height)
view = View.new(self, x, y, width, height)
if block_given?
begin
yield(view)
ensure
view.sync
end
return nil
else
return view
end
end

You use #view like this:

image.view(5, 10, 20, 20) do |view|
view[5][7] = 'yellow'
# other useful stuff...
end



dblack

12/4/2004 12:53:00 AM

0

David G. Andersen

12/4/2004 3:41:00 AM

0

On Sat, Dec 04, 2004 at 09:32:39AM +0900, Joe Van Dyk scribed:
> I come from a heavy C++ background, discovered Ruby a few months ago and
> love it.
>
> I've found that using blocks is a very natural thing. However, I have not
> once used 'yield'. I'm sure that there are events when using yield would be
> helpful, but I have no clue when it would be appropriate to use.
>
> Thoughts? When do you use the 'yield' statement in code?

I use it to pass in an additional filtering routine to
a database selection class. The selection thing knows some
basic stuff like time, but if you want to filter
more precisely,
you can pass it a block:

db_generator = new thingy(start_time, end_time) { |x|
x.attr1 == "frog" && x.attr2 >= 5 }


and then in later code you can grab stuff from the generator
and it's filtered in the way you specified.

-Dave
--
work: dga@lcs.mit.edu me: dga@pobox.com
MIT Laboratory for Computer Science http://www....


Van Dyk, Joe

12/4/2004 4:43:00 AM

0

Sam Stephenson wrote:
> On Sat, 4 Dec 2004 09:32:39 +0900, Joe Van Dyk
> <joe.vandyk@boeing.com> wrote:
>> When do you use the 'yield' statement in code?
>
> When you want to write methods that take blocks.

Yes. What types of methods generally should take blocks?

Joe



gabriele renzi

12/4/2004 11:00:00 AM

0

Joe Van Dyk ha scritto:
> Sam Stephenson wrote:
>
>>On Sat, 4 Dec 2004 09:32:39 +0900, Joe Van Dyk
>><joe.vandyk@boeing.com> wrote:
>>
>>>When do you use the 'yield' statement in code?
>>
>>When you want to write methods that take blocks.
>
>
> Yes. What types of methods generally should take blocks?
>

My little list:
[1] those when behaviour can be further specified.
i.e. #sort and #sort_by can get a block to specify how to sort an object

[2] those where a resource could be freed
i.e. constructors like File.new or Socket.new get a block so that the
undelying resource would be freed when the block ends instead of waiting
for the gc.

[3] those where one would like to lazyly use/reuse a snippet of code
given from the user

i.e. set_trace_func

There are surely others, the best way to get the felling is probably
looking at existing ruby code.

Brian Schröder

12/4/2004 8:21:00 PM

0

On Sat, 4 Dec 2004 09:32:39 +0900
"Joe Van Dyk" <joe.vandyk@boeing.com> wrote:

> I come from a heavy C++ background, discovered Ruby a few months ago and
> love it.
>
> I've found that using blocks is a very natural thing. However, I have not
> once used 'yield'. I'm sure that there are events when using yield would be
> helpful, but I have no clue when it would be appropriate to use.
>
> Thoughts? When do you use the 'yield' statement in code?
>
> Joe

Yield is just a shortcut for block.call.

If I am Lazy, and I don't need to pass the block further I use yield. But I
believe that normally using block.call is more explicit and therefore
preferable.

It may be the case that block.call has a small performance penalty compared
with yield because the block needs to get bound to a variable and therefore be
turned into an object.

Regards,

Brian


--
Brian Schröder
http://ruby.brian-schroeder.de/quiz/... (Spoiler)



dblack

12/4/2004 8:37:00 PM

0

Joel VanderWerf

12/4/2004 8:41:00 PM

0

Brian Schröder wrote:
> Yield is just a shortcut for block.call.

Yield has an advantage: rdoc can recognize it and generate docs for it,
including the names of the variables that are yielded to the block.

The speed advnatage of yield can also be significant, IMHO.


Bill Kelly

12/4/2004 10:45:00 PM

0

Hi,

From: "Joe Van Dyk" <joe.vandyk@boeing.com>
>
> What types of methods generally should take blocks?

My most recent use of yield is in a tree-structured database,
where I wanted to be able to perform {some operation} on a
node and all its children. So,

def apply_all(&block)
yield self
@children.each_value {|n| n.apply_all(&block) } if @children
end

The above is a method of the database node class. It
yields itself, and recursively calls apply_all on all of
its children, so they can yield themselves, etc....
So I can use it like:

some_node.apply_all {|n| n.some_method(foo) }

...to call some_method on some_node and all of its children.



My second most recent use of yield was to do some deferred
processing.

@server.rcon_cmd("dmflags #{dmflags}") do |resp|
@server_state['dmflags'] = dmflags.to_s if resp
end

The above wants to send a command to a server, and when the
response is later received, the block is called to perform
some further processing.

The command gets queued and is processed on different
thread. The block, above, is also passed along...
So that, eventually, when the command has been sent to
the server and the server's response has been received,
the block will be called and passed the server's response
as its argument.

I was particularly thrilled with Ruby when writing this,
because originally my code had been written to NOT queue
the commands to the server, but to send the command
immediately and do a blocking wait for the reply... Like,

if resp = @server.rcon_cmd("dmflags #{dmflags}")
@server_state['dmflags'] = dmflags.to_s
end

So I already had a bunch of code like the above, before I
realized that I really wanted to queue the commands and
process their result later. And you can see how little
I needed to change my code to make that happen!


Hope this helps, just a couple ways I've used yield recently.


Regards,

Bill