define_method with block

L

Leslie Viljoen

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
 
R

Robert Klemme

2008/6/27 Leslie Viljoen said:
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
 
L

Leslie Viljoen

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
)
 
S

Sandro Paganotti

[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


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
)
 
R

Robert Klemme

2008/6/27 Robert Dober said:
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
 
R

Robert Dober

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
 
L

Leslie Viljoen

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
 

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,766
Messages
2,569,569
Members
45,043
Latest member
CannalabsCBDReview

Latest Threads

Top