default passed block for method

N

Niko

Hi all,

I'm trying to define the missing block given in the context of the
method to avoid the block_given? test on each iteration for yield call.

def self.list_of_relationships(relations, source)
# missing_block_that_yield_would_call = lambda { || true } unless
block_given?
relations.map do |relation|
if yield(peer = relation.send(source))
[peer.display_name, peer.id]
end
end.compact
end


Thanks for your help

niko
 
D

dblack

Hi --

Hi all,

I'm trying to define the missing block given in the context of
the method to avoid the block_given? test on each iteration for
yield call.

def self.list_of_relationships(relations, source)
# missing_block_that_yield_would_call = lambda { || true }
unless block_given?
relations.map do |relation|
if yield(peer = relation.send(source))
[peer.display_name, peer.id]
end
end.compact
end

You would want to do:

def self.list(relations,source,&block)
block ||= lambda { true } # no need for empty ||
relations.map do |relation|
if block.call(peer = ....

etc. You'd have to do some benchmarks to find out whether the
slowdown from call is worse than the slowdown from block_given?.


David

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
(See what readers are saying! http://www.rubypal.com/r4rrevs.pdf)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)
 
R

Robert Dober

Hi all,

I'm trying to define the missing block given in the context of the
method to avoid the block_given? test on each iteration for yield call.

def self.list_of_relationships(relations, source)
# missing_block_that_yield_would_call = lambda { || true } unless
block_given?
relations.map do |relation|
if yield(peer = relation.send(source))
[peer.display_name, peer.id]
end
end.compact
end


Thanks for your help

niko
Is the following pattern better for you?
def a &blk
blk ||= proc{true}
blk.call
end

a do
puts "Nice"
end
puts a

HTH
Robert
 
N

Niko

Hi --

Hi all,

I'm trying to define the missing block given in the context of the
method to avoid the block_given? test on each iteration for yield call.

def self.list_of_relationships(relations, source)
# missing_block_that_yield_would_call = lambda { || true } unless
block_given?
relations.map do |relation|
if yield(peer = relation.send(source))
[peer.display_name, peer.id]
end
end.compact
end

You would want to do:

def self.list(relations,source,&block)
block ||= lambda { true } # no need for empty ||
relations.map do |relation|
if block.call(peer = ....

etc. You'd have to do some benchmarks to find out whether the
slowdown from call is worse than the slowdown from block_given?.


David

it works like a charm
i'll do some benchmarks to check the slowdown

thanks for the help
 
B

Brian Candler

I'm trying to define the missing block given in the context of the
method to avoid the block_given? test on each iteration for yield call.

def self.list_of_relationships(relations, source)
# missing_block_that_yield_would_call = lambda { || true } unless
block_given?
relations.map do |relation|
if yield(peer = relation.send(source))
[peer.display_name, peer.id]
end
end.compact
end

def foo(*args, &blk)
blk ||= lambda { true }
blk.call(*args)
end

p foo("123") { |x| "Look: #{x}" }
p foo("456")

It looks like you can't provide a default value for the block in the direct
way:

def foo(*args, &blk = lambda { true } )
# syntax error, unexpected '=', expecting ')'
end

HTH,

Brian.
 
R

Robert Dober

Hi --

Hi all,

I'm trying to define the missing block given in the context of the
method to avoid the block_given? test on each iteration for yield call.

def self.list_of_relationships(relations, source)
# missing_block_that_yield_would_call = lambda { || true } unless
block_given?
relations.map do |relation|
if yield(peer = relation.send(source))
[peer.display_name, peer.id]
end
end.compact
end

You would want to do:

def self.list(relations,source,&block)
block ||= lambda { true } # no need for empty ||
relations.map do |relation|
if block.call(peer = ....

etc. You'd have to do some benchmarks to find out whether the
slowdown from call is worse than the slowdown from block_given?.


David

it works like a charm
i'll do some benchmarks to check the slowdown
they are bad unfortunately, I would not have thought of it, great pointing at
that David.
========================================================
require 'benchmark'

def a1
return true unless block_given?
yield
end
def a2 &blk
blk ||= proc{true}
blk.call
end


Benchmark.bmbm do |x|
x.report("block_given?") {
424242.times do
a1 { 'hi' }
a1
end
}
x.report("&blk") {
424242.times do
a2 { 'hi' }
a2
end
}
end
--------------->

Rehearsal ------------------------------------------------
block_given? 1.280000 0.000000 1.280000 ( 1.310912)
&blk 7.060000 0.020000 7.080000 ( 10.477620)
--------------------------------------- total: 8.360000sec

user system total real
block_given? 1.280000 0.000000 1.280000 ( 1.284248)
&blk 7.090000 0.010000 7.100000 ( 9.274008)

==================================================================
 
J

Joel VanderWerf

Robert said:
Hi --

On Thu, 1 Mar 2007, Niko wrote:


Hi all,

I'm trying to define the missing block given in the context of the
method to avoid the block_given? test on each iteration for yield call.

def self.list_of_relationships(relations, source)
# missing_block_that_yield_would_call = lambda { || true } unless
block_given?
relations.map do |relation|
if yield(peer = relation.send(source))
[peer.display_name, peer.id]
end
end.compact
end

You would want to do:

def self.list(relations,source,&block)
block ||= lambda { true } # no need for empty ||
relations.map do |relation|
if block.call(peer = ....

etc. You'd have to do some benchmarks to find out whether the
slowdown from call is worse than the slowdown from block_given?.


David

it works like a charm
i'll do some benchmarks to check the slowdown
they are bad unfortunately, I would not have thought of it, great
pointing at
that David.
========================================================
require 'benchmark'

def a1
return true unless block_given?
yield
end
def a2 &blk
blk ||= proc{true}
blk.call
end


Benchmark.bmbm do |x|
x.report("block_given?") {
424242.times do
a1 { 'hi' }
a1
end
}
x.report("&blk") {
424242.times do
a2 { 'hi' }
a2
end
}
end
--------------->

Rehearsal ------------------------------------------------
block_given? 1.280000 0.000000 1.280000 ( 1.310912)
&blk 7.060000 0.020000 7.080000 ( 10.477620)
--------------------------------------- total: 8.360000sec

user system total real
block_given? 1.280000 0.000000 1.280000 ( 1.284248)
&blk 7.090000 0.010000 7.100000 ( 9.274008)

==================================================================

That's not really fair to David's suggestion, though, since in the
benchmark you put the loop around the block creation (so you are really
stressing Proc.new). This seems closer to the original example:


require 'benchmark'

def a1 n
n.times do
if block_given?
yield
end
end
end

def a2 n, &blk
blk ||= proc{true}
n.times do
blk.call
end
end


Benchmark.bmbm do |x|
x.report("block_given?") {
a1(424242) { 'hi' }
}
x.report("&blk") {
a2(424242) { 'hi' }
}
end



Rehearsal ------------------------------------------------
block_given? 0.633333 0.000000 0.633333 ( 0.389330)
&blk 1.050000 0.000000 1.050000 ( 0.622025)
--------------------------------------- total: 1.683333sec

user system total real
block_given? 0.650000 0.000000 0.650000 ( 0.384855)
&blk 1.033333 0.000000 1.033333 ( 0.621509)
 
R

Robert Dober

Robert said:
(e-mail address removed) wrote:
Hi --

On Thu, 1 Mar 2007, Niko wrote:


Hi all,

I'm trying to define the missing block given in the context of the
method to avoid the block_given? test on each iteration for yield
call.

def self.list_of_relationships(relations, source)
# missing_block_that_yield_would_call = lambda { || true } unless
block_given?
relations.map do |relation|
if yield(peer = relation.send(source))
[peer.display_name, peer.id]
end
end.compact
end

You would want to do:

def self.list(relations,source,&block)
block ||= lambda { true } # no need for empty ||
relations.map do |relation|
if block.call(peer = ....

etc. You'd have to do some benchmarks to find out whether the
slowdown from call is worse than the slowdown from block_given?.


David


it works like a charm
i'll do some benchmarks to check the slowdown
they are bad unfortunately, I would not have thought of it, great
pointing at
that David.
========================================================
require 'benchmark'

def a1
return true unless block_given?
yield
end
def a2 &blk
blk ||= proc{true}
blk.call
end


Benchmark.bmbm do |x|
x.report("block_given?") {
424242.times do
a1 { 'hi' }
a1
end
}
x.report("&blk") {
424242.times do
a2 { 'hi' }
a2
end
}
end
--------------->

Rehearsal ------------------------------------------------
block_given? 1.280000 0.000000 1.280000 ( 1.310912)
&blk 7.060000 0.020000 7.080000 ( 10.477620)
--------------------------------------- total: 8.360000sec

user system total real
block_given? 1.280000 0.000000 1.280000 ( 1.284248)
&blk 7.090000 0.010000 7.100000 ( 9.274008)

==================================================================

That's not really fair to David's suggestion, though, since in the
Well I benchmarked my suggestion, not David's, probably made another
mistake in my "where to put the post".
However I felt that they were equivalent, do you agree?
benchmark you put the loop around the block creation (so you are really
stressing Proc.new).
Good point, I was missing that Proc.new was so costly and not #call !
But are we not unfair to #block_given? now?

Actually I tried to benchmark the difference between #call and #yield
only and one can see that
block_given? comes almost for free, as I have shown all too well #proc
is very expensive :(.

Therefore your results are pretty correct although you call
block_given way to often, but as it is so cheap..., did you know
maybe?

Thanks in any case for pointing out my error which was *big*.

Cheers
Robert

<snip>
 
R

Rick DeNatale

Just for giggles, I combined Robert and Joel's benchmarks and ran them
on both ruby 1.8 and a quite recent 1.9. Perhaps the results are of
interest.

rick@frodo:/public/rubyscripts$ ruby1.8 blkgiven.rb
Rehearsal -----------------------------------------------------
rd - block_given? 6.070000 1.620000 7.690000 ( 15.323920)
jv - block_given? 3.530000 0.530000 4.060000 ( 9.952521)
rd - &blk 29.620000 2.090000 31.710000 ( 55.018634)
jv - &blk 8.580000 1.400000 9.980000 ( 13.505903)
------------------------------------------- total: 53.440000sec

user system total real
rd - block_given? 6.430000 1.550000 7.980000 ( 12.312925)
jv - block_given? 3.470000 0.630000 4.100000 ( 7.956797)
rd - &blk 28.920000 2.040000 30.960000 ( 55.456023)
jv - &blk 8.860000 1.350000 10.210000 ( 12.264554)


rick@frodo:/public/rubyscripts$ ruby1.9 blkgiven.rb
Rehearsal -----------------------------------------------------
rd - block_given? 1.950000 0.000000 1.950000 ( 2.503581)
jv - block_given? 1.930000 0.010000 1.940000 ( 3.029174)
rd - &blk 10.870000 0.020000 10.890000 ( 21.230573)
jv - &blk 2.430000 0.000000 2.430000 ( 6.296742)
------------------------------------------- total: 17.210000sec

user system total real
rd - block_given? 2.040000 0.010000 2.050000 ( 3.862906)
jv - block_given? 1.770000 0.000000 1.770000 ( 2.239562)
rd - &blk 10.520000 0.050000 10.570000 ( 17.941764)
jv - &blk 2.450000 0.010000 2.460000 ( 3.961397)
rick@frodo:/public/rubyscripts$
 
R

Robert Dober

Just for giggles, I combined Robert and Joel's benchmarks and ran them
on both ruby 1.8 and a quite recent 1.9. Perhaps the results are of
interest.

rick@frodo:/public/rubyscripts$ ruby1.8 blkgiven.rb
Rehearsal -----------------------------------------------------
rd - block_given? 6.070000 1.620000 7.690000 ( 15.323920)
jv - block_given? 3.530000 0.530000 4.060000 ( 9.952521)
rd - &blk 29.620000 2.090000 31.710000 ( 55.018634)
jv - &blk 8.580000 1.400000 9.980000 ( 13.505903)
------------------------------------------- total: 53.440000sec

user system total real
rd - block_given? 6.430000 1.550000 7.980000 ( 12.312925)
jv - block_given? 3.470000 0.630000 4.100000 ( 7.956797)
rd - &blk 28.920000 2.040000 30.960000 ( 55.456023)
jv - &blk 8.860000 1.350000 10.210000 ( 12.264554)


rick@frodo:/public/rubyscripts$ ruby1.9 blkgiven.rb
Rehearsal -----------------------------------------------------
rd - block_given? 1.950000 0.000000 1.950000 ( 2.503581)
jv - block_given? 1.930000 0.010000 1.940000 ( 3.029174)
rd - &blk 10.870000 0.020000 10.890000 ( 21.230573)
jv - &blk 2.430000 0.000000 2.430000 ( 6.296742)
------------------------------------------- total: 17.210000sec

user system total real
rd - block_given? 2.040000 0.010000 2.050000 ( 3.862906)
jv - block_given? 1.770000 0.000000 1.770000 ( 2.239562)
rd - &blk 10.520000 0.050000 10.570000 ( 17.941764)
jv - &blk 2.450000 0.010000 2.460000 ( 3.961397)
rick@frodo:/public/rubyscripts$
---
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Rick I think as a matter of fact that both benchmarks are important.
I was too humble, but that will not happen again ;)

Let us look at Jo=EBl's first, it applies to the following pattern:

def method &blk
blk ||=3D proc{true}
MANY.times do
...
blk.call
...
end
end

from the performance POV you can get away with it.
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
my naive benchmark was benchmarking the following pattern - which
exits quite often too.

def method &blk
blk ||=3D proc{ true }
...
blk.call
...
end

Now of course the proc is a killer as we have as many proces as #call :(

Hopefully this kind of a reasonable conclusion about the performance
cost of the whole stuff.

Cheers
Robert

--=20
We have not succeeded in answering all of our questions.
In fact, in some ways, we are more confused than ever.
But we feel we are confused on a higher level and about more important thin=
gs.
-Anonymous
 
R

Rick DeNatale

Rick I think as a matter of fact that both benchmarks are important.
I was too humble, but that will not happen again ;)

Let us look at Jo=EBl's first, it applies to the following pattern:

def method &blk
blk ||=3D proc{true}
MANY.times do
...
blk.call
...
end
end

from the performance POV you can get away with it.
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D
my naive benchmark was benchmarking the following pattern - which
exits quite often too.

def method &blk
blk ||=3D proc{ true }
...
blk.call
...
end

Now of course the proc is a killer as we have as many proces as #call :(

Hopefully this kind of a reasonable conclusion about the performance
cost of the whole stuff.

I was suggesting that an analysis of how the relative numbers are
changing between 1.8 and 1.9 might be interesting.

Besides the fact that YARV seems quite a bit faster overall, I think
that some of the rules of thumb based on benchmarking on the 'classic'
Ruby implementation are going to change for the new Ruby.

--=20
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/
 
R

Robert Dober

I was suggesting that an analysis of how the relative numbers are
changing between 1.8 and 1.9 might be interesting.

Besides the fact that YARV seems quite a bit faster overall, I think
that some of the rules of thumb based on benchmarking on the 'classic'
Ruby implementation are going to change for the new Ruby.
I thought so Rick, but they seem identical, I mean the same factor of
slowfown for proc and call, right?
Just that YARV runs quite faster :)
 
R

Rick DeNatale

I thought so Rick, but they seem identical, I mean the same factor of
slowfown for proc and call, right?
Just that YARV runs quite faster :)

Not really, here's a cross tabulation (formatting likely to get screwed up)

=09 1.8 1.9 ratio 1.8/1.9
rd -block_given? 6.43=092.04 3.15
rd -&blk=09 28.92 10.52 2.75
ratio 4.5 5.16=09
=09=09=09
jv =96 block_given?=093.47=091.77=09 1.96
jv =96 &blk=09 8.86 2.45 3.62
ratio 2.55 1.38

So for your (Robert's) version of the benchmark the difference between
the two approaches has widened in 1.9, while in Joel's it has
narrowed.

Significant? I don't know, but interesting.
--
We have not succeeded in answering all of our questions.
In fact, in some ways, we are more confused than ever.
But we feel we are confused on a higher level and about more important th= ings.
-Anonymous


--=20
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

IPMS/USA Region 12 Coordinator
http://ipmsr12.denhaven2.com/

Visit the Project Mercury Wiki Site
http://www.mercuryspacecraft.com/
 

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

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,158
Latest member
Vinay_Kumar Nevatia
Top