# About define\_method

**URL:** <https://rubytalk.org/t/about-define-method/66501>\
**Category:** ruby-talk\
**Created:** [15 October 2012 06:37 UTC](https://rubytalk.org/t/about-define-method/66501 "2012-10-15T06:37:10Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![7stud2](https://avatars.discourse-cdn.com/v4/letter/7/9de053/32.png) [@7stud2](https://rubytalk.org/u/7stud2)\
**Post date:** [15 October 2012 06:37 UTC](https://rubytalk.org/t/about-define-method/66501/1 "2012-10-15T06:37:10Z")

</div>

I want to define a method in kernel using Flattern Scope.

&nbsp;&nbsp;Kernel.send :define\_method, :each\_event do  
&nbsp;&nbsp;&nbsp;&nbsp;events.each\_pair do |message, condition|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield message, condition  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end

so, I think this is equal to:

def Kernel.each\_event

&nbsp;&nbsp;&nbsp;&nbsp;events.each\_pair do |message, condition|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield message, condition  
&nbsp;&nbsp;&nbsp;&nbsp;end

end

Then I can pass a block to this method, for example:  
Kernel.each\_event do |message, condition|  
&nbsp;&nbsp;.....  
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:

&nbsp;&nbsp;Kernel.send :define\_method, :each\_event do |&block|  
&nbsp;&nbsp;&nbsp;&nbsp;events.each\_pair do |message, condition|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;block.call message, condition  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end

please help me to figure out why I can not use the first solution.

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)\
**Post date:** [15 October 2012 07:15 UTC](https://rubytalk.org/t/about-define-method/66501/2 "2012-10-15T07:15:15Z")

</div>

You simply cannot define methods which use block passed to them via  
define\_method as you have found out. Minimalistic example:

$ ruby -e 'module Kernel;def foo; yield 1 end end; foo {|x| p x}'  
1  
$ 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'  
for Kernel:Module (NameError)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from -e:1:in `\<main\>'

Another variant is to use class\_eval:

$ ruby -e 'Kernel.class\_eval "def foo; yield 1 end";foo {|x| p x}'  
1

Kind regards

robert

> **···**
>
> On Mon, Oct 15, 2012 at 8:37 AM, li shoubo \<lists@ruby-forum.com\> wrote:
> 
> > please help me to figure out why I can not use the first solution.
> 
> --  
> remember.guy do |as, often| as.you\_can - without end  
> [http://blog.rubybestpractices.com/](http://blog.rubybestpractices.com/)

---

<div class="post-metadata">

**Author:** ![7stud2](https://avatars.discourse-cdn.com/v4/letter/7/9de053/32.png) [@7stud2](https://rubytalk.org/u/7stud2)\
**Post date:** [19 October 2012 22:47 UTC](https://rubytalk.org/t/about-define-method/66501/3 "2012-10-19T22:47:24Z")

</div>

li shoubo wrote in post #1079862:

> I want to define a method in kernel using Flattern Scope.
> 
> &nbsp;&nbsp;Kernel.send :define\_method, :each\_event do  
> &nbsp;&nbsp;&nbsp;&nbsp;events.each\_pair do |message, condition|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield message, condition  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;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:
> 
> &nbsp;&nbsp;Kernel.send :define\_method, :each\_event do |&block|  
> &nbsp;&nbsp;&nbsp;&nbsp;events.each\_pair do |message, condition|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;block.call message, condition  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;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:

&nbsp;&nbsp;Kernel.class\_eval do  
&nbsp;&nbsp;&nbsp;&nbsp;def each\_event(events)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;events.each\_pair do |message, condition|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield message, condition  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end  
&nbsp;&nbsp;events = { one: 1, two: 2, three: 3 }  
&nbsp;&nbsp;each\_event(events) { |x, y| puts "#{x}, #{y}" }

Regards, igor

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![7stud2](https://avatars.discourse-cdn.com/v4/letter/7/9de053/32.png) [@7stud2](https://rubytalk.org/u/7stud2)\
**Post date:** [20 October 2012 03:01 UTC](https://rubytalk.org/t/about-define-method/66501/4 "2012-10-20T03:01:37Z")

</div>

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:

&nbsp;&nbsp;Kernel.send :define\_method, :each\_event do |events, &block|  
&nbsp;&nbsp;&nbsp;&nbsp;events.each\_pair do |message, condition|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;block.call message, condition  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end  
&nbsp;&nbsp;events = { one: 1, two: 2, three: 3 }  
&nbsp;&nbsp;each\_event(events) { |m, c| puts "message:#{m}, condition:#{c}" }

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![7stud2](https://avatars.discourse-cdn.com/v4/letter/7/9de053/32.png) [@7stud2](https://rubytalk.org/u/7stud2)\
**Post date:** [20 October 2012 03:17 UTC](https://rubytalk.org/t/about-define-method/66501/5 "2012-10-20T03:17:25Z")

</div>

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:

&nbsp;&nbsp;Kernel.send :define\_method, :each\_event do |events, &block|  
&nbsp;&nbsp;&nbsp;&nbsp;events.each\_pair do |message, condition|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;block.call message, condition  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end  
&nbsp;&nbsp;events = { one: 1, two: 2, three: 3 }  
&nbsp;&nbsp;each\_event(events) { |m, c| puts "message:#{m}, condition:#{c}" }

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![7stud2](https://avatars.discourse-cdn.com/v4/letter/7/9de053/32.png) [@7stud2](https://rubytalk.org/u/7stud2)\
**Post date:** [15 October 2012 07:34 UTC](https://rubytalk.org/t/about-define-method/66501/6 "2012-10-15T07:34:36Z")

</div>

thanks， I use your example in irb:

module Kernel

&nbsp;&nbsp;&nbsp;define\_method(:foo) { yield 1}

end

no error, but if I invoke it:

Kernel.foo { 2 }

the error jumps,

LocalJumpError: no block given

however， this is OK

module Kernel

&nbsp;&nbsp;&nbsp;define\_method(:foo) { 1 }

end

It seems I can not use yield in define\_method, can you tell me more  
details?

Robert Klemme wrote in post #1079864:

> **···**
>
> > On Mon, Oct 15, 2012 at 8:37 AM, li shoubo \<lists@ruby-forum.com\> wrote:
> > 
> > > please help me to figure out why I can not use the first solution.
> > 
> > You simply cannot define methods which use block passed to them via  
> > define\_method as you have found out. Minimalistic example:
> > 
> > $ ruby -e 'module Kernel;def foo; yield 1 end end; foo {|x| p x}'  
> > 1  
> > $ 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'  
> > for Kernel:Module (NameError)  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from -e:1:in `\<main\>'
> > 
> > Another variant is to use class\_eval:
> > 
> > $ ruby -e 'Kernel.class\_eval "def foo; yield 1 end";foo {|x| p x}'  
> > 1
> > 
> > Kind regards
> > 
> > robert
> 
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Ryan\_Davis1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/ryan_davis1/32/1848_2.png) [@Ryan\_Davis1](https://rubytalk.org/u/Ryan_Davis1)\
**Post date:** [15 October 2012 07:49 UTC](https://rubytalk.org/t/about-define-method/66501/7 "2012-10-15T07:49:17Z")

</div>

you meant :foo

> **···**
>
> 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'

---

<div class="post-metadata">

**Author:** ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)\
**Post date:** [15 October 2012 08:27 UTC](https://rubytalk.org/t/about-define-method/66501/8 "2012-10-15T08:27:40Z")

</div>

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)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;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'
> > 
> > you meant :foo
> 
> --  
> remember.guy do |as, often| as.you\_can - without end  
> [http://blog.rubybestpractices.com/](http://blog.rubybestpractices.com/)

---

<div class="post-metadata">

**Author:** ![7stud2](https://avatars.discourse-cdn.com/v4/letter/7/9de053/32.png) [@7stud2](https://rubytalk.org/u/7stud2)\
**Post date:** [15 October 2012 11:27 UTC](https://rubytalk.org/t/about-define-method/66501/9 "2012-10-15T11:27:32Z")

</div>

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)  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from -e:1:in `\<main\>'
> > 
> > Kind regards
> > 
> > robert
> 
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Robert\_K1](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/robert_k1/32/1830_2.png) [@Robert\_K1](https://rubytalk.org/u/Robert_K1)\
**Post date:** [15 October 2012 12:30 UTC](https://rubytalk.org/t/about-define-method/66501/10 "2012-10-15T12:30:03Z")

</div>

You got it. But you can use Proc#call instead:

irb(main):013:0\> String.send(:define\_method, :foo) {|a, &b| b.call(a +  
length())}  
=\> #\<Proc:0x802b6c4c@(irb):12 (lambda)\>  
irb(main):014:0\> s="bar"  
=\> "bar"  
irb(main):015:0\> s.foo(10) {|x| p x}  
13  
=\> 13

Kind regards

robert

> **···**
>
> On Mon, Oct 15, 2012 at 1:27 PM, li shoubo \<lists@ruby-forum.com\> wrote:
> 
> > 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?
> 
> --  
> remember.guy do |as, often| as.you\_can - without end  
> [http://blog.rubybestpractices.com/](http://blog.rubybestpractices.com/)
