Default passed block for method

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

On 3/1/07, Niko [email protected] wrote:

  if yield(peer = relation.send(source))

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

Hi –

On Thu, 1 Mar 2007, Niko wrote:

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

[email protected] wrote:

def self.list_of_relationships(relations, source)

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

thanks for the help

On Thu, Mar 01, 2007 at 08:41:19PM +0900, Niko wrote:

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.

Robert D. wrote:

method to avoid the block_given? test on each iteration for yield
end

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

        a2 { 'hi' }

              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)

On 3/1/07, Niko [email protected] wrote:

You would want to do:
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)

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

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/

On 3/2/07, Joel VanderWerf [email protected] wrote:

I’m trying to define the missing block given in the context of the
end.compact
slowdown from call is worse than the slowdown from block_given?.
that David.
end
424242.times do
--------------------------------------- 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

On 3/2/07, Rick DeNatale [email protected] wrote:

------------------------------------------- total: 53.440000sec
rd - block_given? 1.950000 0.000000 1.950000 ( 2.503581)
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 :wink:

Let us look at Joël’s first, it applies to the following pattern:

def method &blk
blk ||= proc{true}
MANY.times do

blk.call

end
end

from the performance POV you can get away with it.

my naive benchmark was benchmarking the following pattern - which
exits quite often too.

def method &blk
blk ||= proc{ true }

blk.call

end

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

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

Cheers
Robert

On 3/2/07, Robert D. [email protected] wrote:

jv - &blk 8.580000 1.400000 9.980000 ( 13.505903)
Rehearsal -----------------------------------------------------
jv - &blk 2.450000 0.010000 2.460000 ( 3.961397)
I was too humble, but that will not happen again :wink:
end

end

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

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.


Rick DeNatale

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

On 3/2/07, Rick DeNatale [email protected] wrote:

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 :slight_smile:

On 3/2/07, Robert D. [email protected] wrote:

slowfown for proc and call, right?
Just that YARV runs quite faster :slight_smile:

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

                         1.8      1.9     ratio 1.8/1.9

rd -block_given? 6.43 2.04 3.15
rd -&blk 28.92 10.52 2.75
ratio 4.5 5.16

jv – block_given? 3.47 1.77 1.96
jv – &blk 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 things.
-Anonymous


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/