[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Is there any way to pass further the "hidden" block?

Chiyuan Zhang

12/17/2007 8:12:00 AM

Like this:

def foo
yield
end

def bar(&brk)
foo(&brk)
end

bar { puts "foo" }

What I want to know is: is there any way to define `bar' like this:

def bar
foo
end

so that foo will get the block passed to bar? I want to know this
because I learn from
http://www.pluralsight.com/blogs/dbox/archive/2006/05/09/...
that the implicit block is much faster than explicitly passing it
as &brk . I know one solution is

def bar
foo { yield }
end

but that create another block, not the original one.

13 Answers

Lee Jarvis

12/17/2007 9:43:00 AM

0

Im not sure I fully understand..

But..

def foo(baz)
baz
end

def bar
foo(yield)
end

bar { 'fubar' }
#=> fubar

Perhaps?


Regards,
Lee

--
Posted via http://www.ruby-....

MonkeeSage

12/17/2007 11:57:00 AM

0

On Dec 17, 2:11 am, Chiyuan Zhang <plus...@gmail.com> wrote:
> Like this:
>
> def foo
> yield
> end
>
> def bar(&brk)
> foo(&brk)
> end
>
> bar { puts "foo" }
>
> What I want to know is: is there any way to define `bar' like this:
>
> def bar
> foo
> end
>
> so that foo will get the block passed to bar? I want to know this
> because I learn fromhttp://www.pluralsight.com/blogs/dbox/archive/2006/05/09/...
> that the implicit block is much faster than explicitly passing it
> as &brk . I know one solution is
>
> def bar
> foo { yield }
> end
>
> but that create another block, not the original one.

The article you mention is not loading for me (nor is googles cached
version), so I'm not sure exactly what you mean. When you pass a block
as a parameter, it's just an explicit reference to the implicit block,
not a new copy:

def bar(&blk_2)
puts blk_2.object_id
end
def foo(&blk_1)
puts blk_1.object_id
bar(&blk_1)
end
puts "implicit block"
foo { "baz" }
puts "explicit block"
prc = lambda { "baz" }
puts prc.object_id
foo(&prc)

# =>
implicit block
-605770738
-605770738
explicit block
-605770758
-605770758
-605770758

Although it is slightly slower to grab a reference to the block, it's
probably not anything you have to worry about. E.g., it's only half as
slow over 100,000 calls for this benchmark:

require "benchmark"
def implicit_blk
yield "baz"
end
def explicit_blk(&blk)
blk.call("baz")
end
n = 100_000
Benchmark.bm(10) { | x |
x.report("implicit") { n.times { implicit_blk { | y | y } } }
x.report("explicit") { n.times { explicit_blk { | y | y } } }
}

# =>
user system total real
implicit 0.370000 0.080000 0.450000 ( 0.478676)
explicit 1.200000 0.090000 1.290000 ( 1.324176)

....for me, that's not anything to be concerned about.

Edit: Ah, the cached version of the article you mention just loaded.
Looks like the author got a larger variance in his benchmark. I just
ran the above benchmark again for 1,000,000 calls (like the article),
with these results:

user system total real
implicit 3.520000 0.640000 4.160000 ( 5.230353)
explicit 12.180000 0.850000 13.030000 ( 15.966038)

....so indeed, passing an explicit reference to the block seems to be
exponentially slower. However, still, 3 times slower over a million
calls still doesn't bother me very much. YMMV.

Regards,
Jordan

Trans

12/17/2007 12:52:00 PM

0



On Dec 17, 3:11 am, "Chiyuan Zhang" <plus...@gmail.com> wrote:
> Like this:
>
> def foo
> yield
> end
>
> def bar(&brk)
> foo(&brk)
> end
>
> bar { puts "foo" }
>
> What I want to know is: is there any way to define `bar' like this:
>
> def bar
> foo
> end
>
> so that foo will get the block passed to bar? I want to know this
> because I learn fromhttp://www.pluralsight.com/blogs/dbox/archive/2006/05/09/...
> that the implicit block is much faster than explicitly passing it
> as &brk . I know one solution is
>
> def bar
> foo { yield }
> end
>
> but that create another block, not the original one.

Do you mean, is there a keyword #block to go along with #block_given?
and #yield? As far as I know, there is no way to pass the block except
via an explicit reference.

But I think explicit may be the future. I'm pretty sure I've heard
some chatter about getting rid of #block_given? Technically I would
think it possible to all but eliminate the speed difference between
explicit and implicit --3x seems very high.

T.

MonkeeSage

12/17/2007 1:21:00 PM

0

On Dec 17, 6:52 am, Trans <transf...@gmail.com> wrote:
> On Dec 17, 3:11 am, "Chiyuan Zhang" <plus...@gmail.com> wrote:
>
>
>
> > Like this:
>
> > def foo
> > yield
> > end
>
> > def bar(&brk)
> > foo(&brk)
> > end
>
> > bar { puts "foo" }
>
> > What I want to know is: is there any way to define `bar' like this:
>
> > def bar
> > foo
> > end
>
> > so that foo will get the block passed to bar? I want to know this
> > because I learn fromhttp://www.pluralsight.com/blogs/dbox/archive/2006/05/09/...
> > that the implicit block is much faster than explicitly passing it
> > as &brk . I know one solution is
>
> > def bar
> > foo { yield }
> > end
>
> > but that create another block, not the original one.
>
> Do you mean, is there a keyword #block to go along with #block_given?
> and #yield? As far as I know, there is no way to pass the block except
> via an explicit reference.
>
> But I think explicit may be the future. I'm pretty sure I've heard
> some chatter about getting rid of #block_given? Technically I would
> think it possible to all but eliminate the speed difference between
> explicit and implicit --3x seems very high.
>
> T.

On further testing it appears that in situations where can create a
proc and reuse it, the performance comes much closer (although the
implicit version says the same?!):

require "benchmark"
def implicit_blk
yield "baz"
end
def explicit_blk(&blk)
blk.call("baz")
end
n = 1_000_000
prc = lambda { | y | y }
Benchmark.bm(10) { | x |
x.report("implicit") { n.times { implicit_blk(&prc) } }
x.report("explicit") { n.times { explicit_blk(&prc) } }
}

# =>
user system total real
implicit 3.730000 0.520000 4.250000 ( 4.479818)
explicit 6.000000 0.580000 6.580000 ( 6.763514)

....wonder why?

Regards,
Jordan

MonkeeSage

12/18/2007 1:49:00 AM

0

Hmmm...another thing...passing prc to #explicit_blk as an lval rather
than invoking block_pass shaves another second off the time...

def explicit_blk(blk)
blk.call("baz")
end
n = 1_000_000
prc = lambda { | y | y }
Benchmark.bm(10) { | x |
x.report("explicit") { n.times { explicit_blk(prc) } }
}

# =>
user system total real
explicit 5.030000 0.520000 5.550000 ( 5.774020)

....so I'm curious about two matters:

1.) Why does creating a Proc explicitly and passing it as a block_arg
rather than using a literal block (see previous post) speed up the
#explicit_blk benchmark 2 times, but doesn't have very much effect the
#implicit_blk benchmark?

2.) Why is it less expensive to pass a Proc as an lval rather than as
a block_arg?

Anybody know?

Regards,
Jordan

Gary Wright

12/18/2007 3:47:00 AM

0


On Dec 17, 2007, at 3:11 AM, Chiyuan Zhang wrote:
> def bar
> foo { yield }
> end
>
> but that create another block, not the original one.

This is the only technique I'm aware of. I it
is still faster than explicitly reifying the outer block
before calling foo.

Somewhat related: Super will pass along an implicit
block. To disable this do:

super(a, b, &nil)

Gary Wright



Chiyuan Zhang

12/18/2007 6:20:00 AM

0

Hmm... what i'm looking for is just like super. As all you mentioned
above, maybe there's no such feature yet. :)

2007/12/18, Gary Wright <gwtmp01@mac.com>:
>
> On Dec 17, 2007, at 3:11 AM, Chiyuan Zhang wrote:
> > def bar
> > foo { yield }
> > end
> >
> > but that create another block, not the original one.
>
> This is the only technique I'm aware of. I it
> is still faster than explicitly reifying the outer block
> before calling foo.
>
> Somewhat related: Super will pass along an implicit
> block. To disable this do:
>
> super(a, b, &nil)
>
> Gary Wright
>
>
>
>

MonkeeSage

12/21/2007 12:38:00 PM

0

On Dec 17, 7:49 pm, MonkeeSage <MonkeeS...@gmail.com> wrote:
> Hmmm...another thing...passing prc to #explicit_blk as an lval rather
> than invoking block_pass shaves another second off the time...
>
> def explicit_blk(blk)
> blk.call("baz")
> end
> n = 1_000_000
> prc = lambda { | y | y }
> Benchmark.bm(10) { | x |
> x.report("explicit") { n.times { explicit_blk(prc) } }
>
> }
>
> # =>
> user system total real
> explicit 5.030000 0.520000 5.550000 ( 5.774020)
>
> ...so I'm curious about two matters:
>
> 1.) Why does creating a Proc explicitly and passing it as a block_arg
> rather than using a literal block (see previous post) speed up the
> #explicit_blk benchmark 2 times, but doesn't have very much effect the
> #implicit_blk benchmark?
>
> 2.) Why is it less expensive to pass a Proc as an lval rather than as
> a block_arg?
>
> Anybody know?
>
> Regards,
> Jordan

Bump

Robert Dober

12/21/2007 4:40:00 PM

0

On Dec 17, 2007 9:11 AM, Chiyuan Zhang <pluskid@gmail.com> wrote:
<snip>
> def bar
> foo { yield }
> end

def bar
foo &Proc.new
end

HTH
Robert
--

http://ruby-smalltalk.blo...

---
All truth passes through three stages. First, it is ridiculed. Second,
it is violently opposed. Third, it is accepted as being self-evident.
Schopenhauer (attr.)

MonkeeSage

12/24/2007 10:48:00 PM

0

On Dec 21, 6:38 am, MonkeeSage <MonkeeS...@gmail.com> wrote:
> On Dec 17, 7:49 pm, MonkeeSage <MonkeeS...@gmail.com> wrote:
>
>
>
> > Hmmm...another thing...passing prc to #explicit_blk as an lval rather
> > than invoking block_pass shaves another second off the time...
>
> > def explicit_blk(blk)
> > blk.call("baz")
> > end
> > n = 1_000_000
> > prc = lambda { | y | y }
> > Benchmark.bm(10) { | x |
> > x.report("explicit") { n.times { explicit_blk(prc) } }
>
> > }
>
> > # =>
> > user system total real
> > explicit 5.030000 0.520000 5.550000 ( 5.774020)
>
> > ...so I'm curious about two matters:
>
> > 1.) Why does creating a Proc explicitly and passing it as a block_arg
> > rather than using a literal block (see previous post) speed up the
> > #explicit_blk benchmark 2 times, but doesn't have very much effect the
> > #implicit_blk benchmark?
>
> > 2.) Why is it less expensive to pass a Proc as an lval rather than as
> > a block_arg?
>
> > Anybody know?
>
> > Regards,
> > Jordan
>
> Bump

Bump...anyone have any idea about the two questions I asked?