How to change the owner of a method in a block?

Hi, let me explain with this simple code:

···

--------------------
class A

  def initialize(&blk)
    blk.call
  end

  def hello
    puts "HELLO !!!"
  end

end

a=A.new { hello() }

=> block_1.rb:13: undefined method `hello' for main:Object (NoMethodError)
        from block_1.rb:4:in `call'
        from block_1.rb:4:in `initialize'
        from block_1.rb:13:in `new'
        from block_1.rb:13
---------------------------------

I understand perfectly what occurs: When passing "hello()" in a block,
it's like if the current object is "main:Object", for which there is
no "hello" method (of course).

Well, I'd like that "hello()" would be runned as class A instance
method. Is it possible is some ellegant way?

Thanks a lot.

--
Iñaki Baz Castillo
<ibc@aliax.net>

Lex Williams wrote:

one way would be to use instance_eval :

def new(&blk)
   instance_eval &blk
end

I meant to write :

def initialize(&blk)
    instance_eval &blk
end

too much java can get you high .

···

--
Posted via http://www.ruby-forum.com/\.

Lex Williams wrote:
> one way would be to use instance_eval :
>
> def new(&blk)
> instance_eval &blk
> end

I meant to write :

  def initialize(&blk)
    instance_eval &blk
  end

Really great :slight_smile:

Let me just a question: how does affect using "instance_eval" in
performance? I've done some simple tests:

Benchmark.realtime { a=123; a2=a*2; a3=a*3 }

# => 1.97887420654297e-05

Benchmark.realtime { instance_eval 'a=123; a2=a*2; a3=a*3' }

# => 4.50611114501953e-05

Well, it seems that using "instance_eval" takes the double of time
than running the code directly. Is it significant?

Thanks.

···

2008/9/10, Lex Williams <etaern@yahoo.com>:

--
Iñaki Baz Castillo
<ibc@aliax.net>

# >> Benchmark.realtime { instance_eval 'a=123; a2=a*2; a3=a*3' }
# # => 4.50611114501953e-05

that's a string.

include a block, eg

Benchmark.realtime { a=123; a2=a*2; a3=a*3 }

=> 1.59740447998047e-05

Benchmark.realtime { instance_eval 'a=123; a2=a*2; a3=a*3' }

=> 7.58171081542969e-05

Benchmark.realtime { instance_eval {a=123; a2=a*2; a3=a*3} }

=> 2.288818359375e-05

···

From: Iñaki Baz Castillo [mailto:ibc@aliax.net]

You are right!
So using "instance_eval" is ~ 40% slower than running directly the code.

Thanks a lot.

···

2008/9/10, Peña, Botp <botp@delmonte-phil.com>:

From: Iñaki Baz Castillo [mailto:ibc@aliax.net]
# >> Benchmark.realtime { instance_eval 'a=123; a2=a*2; a3=a*3' }
# # => 4.50611114501953e-05

that's a string.

include a block, eg

> Benchmark.realtime { a=123; a2=a*2; a3=a*3 }

=> 1.59740447998047e-05

> Benchmark.realtime { instance_eval 'a=123; a2=a*2; a3=a*3' }

=> 7.58171081542969e-05

> Benchmark.realtime { instance_eval {a=123; a2=a*2; a3=a*3} }

=> 2.288818359375e-05

--
Iñaki Baz Castillo
<ibc@aliax.net>

well, we can try again :slight_smile:

botp@jedi-hopeful:~$ cat test.rb
require 'benchmark'
n=100_000
Benchmark.bmbm do |x|
  x.report("normal") { n.times { a=nil;a=123; a2=a*2; a3=a*3 }}
  x.report("string") { n.times {instance_eval 'a=nil;a=123; a2=a*2; a3=a*3' }}
  x.report("block") { n.times {instance_eval {a=nil;a=123; a2=a*2; a3=a*3} }}
  x.report("block-broken") { n.times {a=nil;instance_eval{a=123};
                                      instance_eval{ a2=a*2};
                                      instance_eval{a3=a*3}
                                      }
                            }
end

botp@jedi-hopeful:~$ ruby test.rb
Rehearsal ------------------------------------------------
normal 0.140000 0.000000 0.140000 ( 0.247775)
string 2.420000 0.010000 2.430000 ( 3.438391)
block 0.250000 0.000000 0.250000 ( 0.375656)
block-broken 0.470000 0.010000 0.480000 ( 0.698093)
--------------------------------------- total: 3.300000sec

                   user system total real
normal 0.120000 0.000000 0.120000 ( 0.216789)
string 2.480000 0.020000 2.500000 ( 3.291342)
block 0.300000 0.000000 0.300000 ( 0.423327)
block-broken 0.490000 0.000000 0.490000 ( 0.703046)
botp@jedi-hopeful:~$

slower but not slow (in my own mileage :slight_smile:
or optimistically, direct code is faster than a code block

···

On Wed, Sep 10, 2008 at 7:24 PM, Iñaki Baz Castillo <ibc@aliax.net> wrote:

So using "instance_eval" is ~ 40% slower than running directly the code.

Good comparision, thanks :slight_smile:

···

El Jueves, 11 de Septiembre de 2008, botp escribió:

On Wed, Sep 10, 2008 at 7:24 PM, Iñaki Baz Castillo <ibc@aliax.net> wrote:
> So using "instance_eval" is ~ 40% slower than running directly the code.

well, we can try again :slight_smile:

botp@jedi-hopeful:~$ cat test.rb
require 'benchmark'
n=100_000
Benchmark.bmbm do |x|
  x.report("normal") { n.times { a=nil;a=123; a2=a*2; a3=a*3 }}
  x.report("string") { n.times {instance_eval 'a=nil;a=123; a2=a*2; a3=a*3'
}} x.report("block") { n.times {instance_eval {a=nil;a=123; a2=a*2; a3=a*3}
}} x.report("block-broken") { n.times {a=nil;instance_eval{a=123};
                                      instance_eval{ a2=a*2};
                                      instance_eval{a3=a*3}
                                      }
                            }
end

botp@jedi-hopeful:~$ ruby test.rb
Rehearsal ------------------------------------------------
normal 0.140000 0.000000 0.140000 ( 0.247775)
string 2.420000 0.010000 2.430000 ( 3.438391)
block 0.250000 0.000000 0.250000 ( 0.375656)
block-broken 0.470000 0.010000 0.480000 ( 0.698093)
--------------------------------------- total: 3.300000sec

                   user system total real
normal 0.120000 0.000000 0.120000 ( 0.216789)
string 2.480000 0.020000 2.500000 ( 3.291342)
block 0.300000 0.000000 0.300000 ( 0.423327)
block-broken 0.490000 0.000000 0.490000 ( 0.703046)
botp@jedi-hopeful:~$

slower but not slow (in my own mileage :slight_smile:
or optimistically, direct code is faster than a code block

--
Iñaki Baz Castillo