I want to define a method in kernel using Flattern Scope.
Kernel.send :define_method, :each_event do
events.each_pair do |message, condition|
yield message, condition
end
end
. . .
However, if I use send define_method method to define each_event, I
would met a exception:
in `each_event': no block given (LocalJumpError)
I do not know why? if I do not use "send", the "yield" work well. Also,
I can define method as follows according to "meta programming ruby"
says:
Kernel.send :define_method, :each_event do |&block|
events.each_pair do |message, condition|
block.call message, condition
end
end
The problem is not the 'send', but rather the 'define_method'. Namely,
'define_method' does not allow you to specify a method body that expects
a blok. If you need to dynamically create a method that accepts a block,
you need to use the 'def method_name; ...; end' and the 'class_eval'
(see: D. Flanagan's & Y. Matsumoto's book 'The Ruby Programming
Language' page:275).
So, your example should look something like the following:
Kernel.class_eval do
def each_event(events)
events.each_pair do |message, condition|
yield message, condition
end
end
end
events = { one: 1, two: 2, three: 3 }
each_event(events) { |x, y| puts "#{x}, #{y}" }
I looked at all the posts above again, and realized that both, you li,
and
Robert, have already presented the proper solution to your original
post. In fact you yourself, li, offered the solution at the end of your
first post above. Namely, contrary to the quote in 'The Ruby Programming
Language' book, the following code with 'define_method' works just fine:
Kernel.send :define_method, :each_event do |events, &block|
events.each_pair do |message, condition|
block.call message, condition
end
end
events = { one: 1, two: 2, three: 3 }
each_event(events) { |m, c| puts "message:#{m}, condition:#{c}" }
I looked at all the posts again, and realized that both, you li, and
Robert, have already presented the proper solution to your original
post. In fact you yourself, li, offered the solution at the end of your
first post above. Namely, contrary to the quote in 'The Ruby Programming
Language' book, the following code with 'define_method' works just fine:
Kernel.send :define_method, :each_event do |events, &block|
events.each_pair do |message, condition|
block.call message, condition
end
end
events = { one: 1, two: 2, three: 3 }
each_event(events) { |m, c| puts "message:#{m}, condition:#{c}" }
Yes, of course. Thanks for catching that. Then we get
$ ruby -e 'module Kernel;define_method(:foo) { yield 1 };end;foo {|x| p x}'
-e:1:in `block in <module:Kernel>': no block given (yield) (LocalJumpError)
from -e:1:in `<main>'
Kind regards
robert
···
On Mon, Oct 15, 2012 at 9:49 AM, Ryan Davis <ryand-ruby@zenspider.com> wrote:
On Oct 15, 2012, at 00:15 , Robert Klemme <shortcutter@googlemail.com> wrote:
$ ruby -e 'module Kernel;define_method(foo) { yield 1 };end;foo {|x| p x}'
-e:1:in `<module:Kernel>': undefined local variable or method `foo'
can you give me more details? Or it is a rule that I can not use yield
in define_method method to define a new one?
Robert Klemme wrote in post #1079874:
···
On Mon, Oct 15, 2012 at 9:49 AM, Ryan Davis <ryand-ruby@zenspider.com> > wrote:
On Oct 15, 2012, at 00:15 , Robert Klemme <shortcutter@googlemail.com> wrote:
$ ruby -e 'module Kernel;define_method(foo) { yield 1 };end;foo {|x| p x}'
-e:1:in `<module:Kernel>': undefined local variable or method `foo'
you meant :foo
Yes, of course. Thanks for catching that. Then we get
$ ruby -e 'module Kernel;define_method(:foo) { yield 1 };end;foo {|x| p
x}'
-e:1:in `block in <module:Kernel>': no block given (yield)
(LocalJumpError)
from -e:1:in `<main>'