Method Definitions: &block vs. yield()

J

James H.

Suppose I had two methods:

# First method
def my_first_method(b)
yield b
end

# Second method
def my_second_method(&block)
block.call
end

I know that the block in the 2nd example is converted to a Proc object,
but a Proc object (to my newb eyes) doesn't seem to hold any advantages
that might make me want to use the latter method.

I was wondering if there are specific advantages to using the &block
convention or yield()ing a block? Is it merely a matter of preference
and or convention?

James
 
A

ara.t.howard

Suppose I had two methods:

# First method
def my_first_method(b)
yield b
end

# Second method
def my_second_method(&block)
block.call
end

I know that the block in the 2nd example is converted to a Proc object,
but a Proc object (to my newb eyes) doesn't seem to hold any advantages
that might make me want to use the latter method.

I was wondering if there are specific advantages to using the &block
convention or yield()ing a block? Is it merely a matter of preference
and or convention?

James


harp:~ > cat a.rb
class C
def foo(&b) bar &b end
def bar() yield end
end
C::new.foo{ p 42 }


harp:~ > ruby a.rb
42


-a
 
J

Joel VanderWerf

James said:
Suppose I had two methods:

# First method
def my_first_method(b)
yield b
end

# Second method
def my_second_method(&block)
block.call
end

to be really comparable:

def my_second_method(b, &block)
block.call(b)
end
I know that the block in the 2nd example is converted to a Proc object,
but a Proc object (to my newb eyes) doesn't seem to hold any advantages
that might make me want to use the latter method.

I was wondering if there are specific advantages to using the &block
convention or yield()ing a block? Is it merely a matter of preference
and or convention?

Yield is lighter weight, since no Proc is created. Also, when a Proc is
created, it's binding is stored, and that binding includes any variables
in scope in the proc. As long as you hang on to that Proc, the values of
those variables cannot be GC-ed.

But with yield, you can only call the block from within the scope of the
method. If you need to store it away somewhere and call it after
returning, then you have to use a Proc.
 
M

Marcin Mielżyński

James H. wrote:

Generally yield is much faster than converting block to a Proc. But
there are situations when you have to explicitly pass the block and
convert it, these two are the most obvious that come to my mind:

saving a Proc object for delayed execution
implementing recursive iterators

lopex
 
R

Robert Klemme

Marcin said:
James H. wrote:

Generally yield is much faster than converting block to a Proc. But
there are situations when you have to explicitly pass the block and
convert it, these two are the most obvious that come to my mind:

saving a Proc object for delayed execution
implementing recursive iterators

More generally all situations where you do not want to invoke the block
from this method but pass it on to another.

Kind regards

robert
 
J

Jacob Fugal

T24gMi83LzA2LCBSb2JlcnQgS2xlbW1lIDxib2IubmV3c0BnbXgubmV0PiB3cm90ZToKPiBNYXJj
aW4gTWllbL958XNraSB3cm90ZToKPiA+IEphbWVzIEguIHdyb3RlOgo+ID4KPiA+IEdlbmVyYWxs
eSB5aWVsZCBpcyBtdWNoIGZhc3RlciB0aGFuIGNvbnZlcnRpbmcgYmxvY2sgdG8gYSBQcm9jLiBC
dXQKPiA+IHRoZXJlIGFyZSBzaXR1YXRpb25zIHdoZW4geW91IGhhdmUgdG8gZXhwbGljaXRseSBw
YXNzIHRoZSBibG9jayBhbmQKPiA+IGNvbnZlcnQgaXQsIHRoZXNlIHR3byBhcmUgdGhlIG1vc3Qg
b2J2aW91cyB0aGF0IGNvbWUgdG8gbXkgbWluZDoKPiA+Cj4gPiBzYXZpbmcgYSBQcm9jIG9iamVj
dCBmb3IgZGVsYXllZCBleGVjdXRpb24KPiA+IGltcGxlbWVudGluZyByZWN1cnNpdmUgaXRlcmF0
b3JzCj4KPiBNb3JlIGdlbmVyYWxseSBhbGwgc2l0dWF0aW9ucyB3aGVyZSB5b3UgZG8gbm90IHdh
bnQgdG8gaW52b2tlIHRoZSBibG9jawo+IGZyb20gdGhpcyBtZXRob2QgYnV0IHBhc3MgaXQgb24g
dG8gYW5vdGhlci4KCihvciBib3RoKQoKSmFjb2IgRnVnYWwK
 
G

gwtmp01

But with yield, you can only call the block from within the scope
of the method. If you need to store it away somewhere and call it
after returning, then you have to use a Proc.

You can pass an implicit block to another method by wrapping it in
another block:

class Example

def m1
m2 { yield }
end

def m2
yield
end

end

e1 = Example.new

e1.m1 { p 42 }

There is no explicit reification of a block to a Proc object
in this example. This technique can avoid the creation of
a Proc object in many common situations, but certainly not
in all cases.


Gary Wright
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,216
Latest member
topweb3twitterchannels

Latest Threads

Top