[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

define_method with block

Leslie Viljoen

6/27/2008 11:22:00 AM

Hi!

Is there a way that methods defined with define_method can take a block?
Here's my fighting module:

module Taikwando
def self.add_warrior(n)
define_method(n) do
puts "#{n} fights!"
yield
end
end

def fight(*names)
names.each do |n|
Taikwando.add_warrior(n)
end
end
end

include Taikwando



..when I require it, I can do this:

>> fight "morpheus", "neo"
=> ["morpheus", "neo"]
>> neo do
?> puts "karate chop!"
>> end
neo fights!
LocalJumpError: no block given
from ./kungfu.rb:102:in `neo'
from (irb):5


- the yield does not work. Any ideas?

Les

7 Answers

Robert Klemme

6/27/2008 11:30:00 AM

0

2008/6/27 Leslie Viljoen <leslieviljoen@gmail.com>:

> Is there a way that methods defined with define_method can take a block?
> Here's my fighting module:
>
> module Taikwando
> def self.add_warrior(n)
> define_method(n) do
> puts "#{n} fights!"
> yield
> end
> end
>
> def fight(*names)
> names.each do |n|
> Taikwando.add_warrior(n)
> end
> end
> end
>
> include Taikwando
>
>
>
> ..when I require it, I can do this:
>
>>> fight "morpheus", "neo"
> => ["morpheus", "neo"]
>>> neo do
> ?> puts "karate chop!"
>>> end
> neo fights!
> LocalJumpError: no block given
> from ./kungfu.rb:102:in `neo'
> from (irb):5
>
>
> - the yield does not work. Any ideas?

AFAIK there is no way (yet) to define a method that needs a block via
define_method. I believe you can try to work around this by doing

self.class.class_eval "def #{m}; puts '#{m} fights'; yield; end"

Kind regards

robert


--
use.inject do |as, often| as.you_can - without end

Leslie Viljoen

6/27/2008 11:48:00 AM

0

On 6/27/08, Robert Klemme <shortcutter@googlemail.com> wrote:
> 2008/6/27 Leslie Viljoen <leslieviljoen@gmail.com>:
>
>
> > Is there a way that methods defined with define_method can take a block?
> > Here's my fighting module:
> >
> > module Taikwando
> > def self.add_warrior(n)
> > define_method(n) do
> > puts "#{n} fights!"
> > yield
> > end
> > end
> >
> > def fight(*names)
> > names.each do |n|
> > Taikwando.add_warrior(n)
> > end
> > end
> > end
> >
> > include Taikwando
> >
> >
> >
> > ..when I require it, I can do this:
> >
> >>> fight "morpheus", "neo"
> > => ["morpheus", "neo"]
> >>> neo do
> > ?> puts "karate chop!"
> >>> end
> > neo fights!
> > LocalJumpError: no block given
> > from ./kungfu.rb:102:in `neo'
> > from (irb):5
> >
> >
> > - the yield does not work. Any ideas?
>
>
> AFAIK there is no way (yet) to define a method that needs a block via
> define_method. I believe you can try to work around this by doing
>
> self.class.class_eval "def #{m}; puts '#{m} fights'; yield; end"
>
> Kind regards
>
> robert
>

I can explicitly pass a block to my fight method too, but it's so ugly:
neo(lambda do
puts "flying kick"
end
)




>
> --
> use.inject do |as, often| as.you_can - without end
>
>


--
[we need your code-fu] : www.zadic.co.za

Sandro Paganotti

6/27/2008 12:05:00 PM

0

[Note: parts of this message were removed to make it a legal post.]

I've re-arranged a bit your code... maybe this way can be more nice-looking:
module Taikwando
def self.add_warrior(n)
define_method(n) do |blk|
puts "#{n} fights!"
blk.call
end
end

def fight(*names)
names.each do |n|
Taikwando.add_warrior(n)
end
end

def moves (fighter,&block)
self.send(fighter,block)
end
end

include Taikwando

fight "morpheus", "neo"
moves("neo") do
puts "karate chop!"
end


On Fri, Jun 27, 2008 at 11:48 AM, Leslie Viljoen <leslieviljoen@gmail.com>
wrote:

> On 6/27/08, Robert Klemme <shortcutter@googlemail.com> wrote:
> > 2008/6/27 Leslie Viljoen <leslieviljoen@gmail.com>:
> >
> >
> > > Is there a way that methods defined with define_method can take a
> block?
> > > Here's my fighting module:
> > >
> > > module Taikwando
> > > def self.add_warrior(n)
> > > define_method(n) do
> > > puts "#{n} fights!"
> > > yield
> > > end
> > > end
> > >
> > > def fight(*names)
> > > names.each do |n|
> > > Taikwando.add_warrior(n)
> > > end
> > > end
> > > end
> > >
> > > include Taikwando
> > >
> > >
> > >
> > > ..when I require it, I can do this:
> > >
> > >>> fight "morpheus", "neo"
> > > => ["morpheus", "neo"]
> > >>> neo do
> > > ?> puts "karate chop!"
> > >>> end
> > > neo fights!
> > > LocalJumpError: no block given
> > > from ./kungfu.rb:102:in `neo'
> > > from (irb):5
> > >
> > >
> > > - the yield does not work. Any ideas?
> >
> >
> > AFAIK there is no way (yet) to define a method that needs a block via
> > define_method. I believe you can try to work around this by doing
> >
> > self.class.class_eval "def #{m}; puts '#{m} fights'; yield; end"
> >
> > Kind regards
> >
> > robert
> >
>
> I can explicitly pass a block to my fight method too, but it's so ugly:
> neo(lambda do
> puts "flying kick"
> end
> )
>
>
>
>
> >
> > --
> > use.inject do |as, often| as.you_can - without end
> >
> >
>
>
> --
> [we need your code-fu] : www.zadic.co.za
>
>


--
Dan Quayle - "It's time for the human race to enter the solar system."

Robert Dober

6/27/2008 12:48:00 PM

0

On Fri, Jun 27, 2008 at 1:21 PM, Leslie Viljoen <leslieviljoen@gmail.com> wrote:
> Hi!
>
> Is there a way that methods defined with define_method can take a block?
Short answers
1.8 : No
1.9 : Yes
HTH
Robert

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

---
AALST (n.) One who changes his name to be further to the front
D.Adams; The Meaning of LIFF

Robert Klemme

6/27/2008 2:45:00 PM

0

2008/6/27 Robert Dober <robert.dober@gmail.com>:
> On Fri, Jun 27, 2008 at 1:21 PM, Leslie Viljoen <leslieviljoen@gmail.com> wrote:
>> Hi!
>>
>> Is there a way that methods defined with define_method can take a block?
> Short answers
> 1.8 : No
> 1.9 : Yes

1.9 is still a bit inconsistent here IMHO:

irb(main):001:0> RUBY_VERSION
=> "1.9.0"
irb(main):002:0> class Foo
irb(main):003:1> define_method(:bar) do
irb(main):004:2* yield 123
irb(main):005:2> end
irb(main):006:1> end
=> #<Proc:0x7feeea10@(irb):4 (lambda)>
irb(main):007:0> Foo.new.bar {|x| p x}
LocalJumpError: no block given (yield)
from (irb):4:in `block (1 levels) in <class:Foo>'
from (irb):7
from /opt/lib/ruby/1.9.0/irb.rb:149:in `block (2 levels) in eval_input'
from /opt/lib/ruby/1.9.0/irb.rb:262:in `signal_status'
from /opt/lib/ruby/1.9.0/irb.rb:146:in `block in eval_input'
from /opt/lib/ruby/1.9.0/irb.rb:145:in `eval_input'
from /opt/lib/ruby/1.9.0/irb.rb:69:in `block in start'
from /opt/lib/ruby/1.9.0/irb.rb:68:in `catch'
from /opt/lib/ruby/1.9.0/irb.rb:68:in `start'
from /opt/bin/irb19:12:in `<main>'
irb(main):008:0> class Foo
irb(main):009:1> define_method(:bar) do |&b|
irb(main):010:2* b[123]
irb(main):011:2> end
irb(main):012:1> end
=> #<Proc:0x7fee49c0@(irb):10 (lambda)>
irb(main):013:0> Foo.new.bar {|x| p x}
123
=> 123
irb(main):014:0>

Kind regards

robert

--
use.inject do |as, often| as.you_can - without end

Robert Dober

6/27/2008 7:03:00 PM

0

On Fri, Jun 27, 2008 at 4:45 PM, Robert Klemme
<shortcutter@googlemail.com> wrote:
> 2008/6/27 Robert Dober <robert.dober@gmail.com>:
>> On Fri, Jun 27, 2008 at 1:21 PM, Leslie Viljoen <leslieviljoen@gmail.com> wrote:
>>> Hi!
>>>
>>> Is there a way that methods defined with define_method can take a block?
>> Short answers
>> 1.8 : No
>> 1.9 : Yes
Good of Robert to point out that 1.9 is not yet stable of course, but
this is a feature that will work :).
Cheers
Robert



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

---
AALST (n.) One who changes his name to be further to the front
D.Adams; The Meaning of LIFF

Leslie Viljoen

6/27/2008 8:03:00 PM

0

On 6/27/08, Sandro Paganotti <sandro.paganotti@gmail.com> wrote:
> I've re-arranged a bit your code... maybe this way can be more nice-looking:
>
> module Taikwando
> def self.add_warrior(n)
>
> define_method(n) do |blk|
> puts "#{n} fights!"
> blk.call
>
> end
> end
>
> def fight(*names)
> names.each do |n|
> Taikwando.add_warrior(n)
> end
> end
>
>
> def moves (fighter,&block)
> self.send(fighter,block)
> end
> end
>
> include Taikwando
>
> fight "morpheus", "neo"
> moves("neo") do
> puts "karate chop!"
> end

Ok, that's a bit better, thanks!

Les