Define_method with block

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

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

···

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?

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

Short answers
1.8 : No
1.9 : Yes
HTH
Robert

···

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?

--
http://ruby-smalltalk.blogspot.com/

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

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

···

On 6/27/08, Robert Klemme <shortcutter@googlemail.com> wrote:

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

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

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

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

···

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

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

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."

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

···

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

--
http://ruby-smalltalk.blogspot.com/

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

Ok, that's a bit better, thanks!

Les

···

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