# Dynamicaly define a method which body can contain yield

**URL:** <https://www.ruby-forum.com/t/dynamicaly-define-a-method-which-body-can-contain-yield/189583>\
**Category:** Ruby\
**Created:** [June 3, 2010, 3:28pm UTC](https://www.ruby-forum.com/t/dynamicaly-define-a-method-which-body-can-contain-yield/189583 "2010-06-03T15:28:43Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![raubarede](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/d07c76/32.png) [@raubarede](https://www.ruby-forum.com/u/raubarede)\
**Post date:** [June 3, 2010, 3:28pm UTC](https://www.ruby-forum.com/t/dynamicaly-define-a-method-which-body-can-contain-yield/189583/1 "2010-06-03T15:28:43Z")

</div>

Hello,

So i try to define a methode by providing a bloc which can contain a  
yield.

I got a error ‘no block given (yield)’ on yield execution

Here is my test code :  
class B  
def p1 ; puts “p1”; end  
def p2 ; puts “p2 1” ; yield ; puts “p2 2” ; end  
def self.add\_tag(name,&blk)  
puts “defined #{name}…”  
define\_method(name) do  
instance\_eval(&blk)  
end  
end  
def self.add\_tag2(name,str\_bloc)  
puts “defined2 #{name}…”  
module\_eval %{  
def #{name}()  
#{str\_bloc}  
end  
}  
end  
end

add\_tag2 work well, but is not pretty :

> B.add\_tag2 “p4” “puts 'p4 '; p1 ; p2 { puts ‘inp2’ } ; yield”  
> defined2 p4…  
> =\> nil  
> b.p4 { puts ‘in p4’ }  
> p4  
> p1  
> p2 1  
> inp2  
> p2 2  
> in p4  
> =\> nil

add\_tag give a Exception if bloc contain a yield:

> B.add\_tag(“p5”) { puts 'p5 ‘; yield }  
> defined p5…  
> =\> #Proc:0x027edcd4@./essai.rb:6  
> b.p5 { puts ‘in p5’ }  
> p5  
> LocalJumpError: no block given  
> from (irb):14  
> from ./essai.rb:7:in `instance_eval' from ./essai.rb:7:in`p5’  
> from (irb):15  
> from :0

Is there a solution ?  
Thank you!

---

<div class="post-metadata">

**Author:** ![raubarede](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/d07c76/32.png) [@raubarede](https://www.ruby-forum.com/u/raubarede)\
**Post date:** [June 3, 2010, 5:05pm UTC](https://www.ruby-forum.com/t/dynamicaly-define-a-method-which-body-can-contain-yield/189583/2 "2010-06-03T17:05:16Z")

</div>

On Thu, Jun 3, 2010 at 3:28 PM, Regis d’Aubarede  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Hello,
> 
> So i try to define a methode by providing a bloc which can contain a  
> yield.  
> This is known as the single biggest PITA of Ruby1.8, well by me.  
> If you can, use Ruby1.9 and you can do such wonderful things as  
> define\_method :alpha do |beta, &gamma|  
> . .  
> gamma[…]  
> …  
> end

in 1.8. you have to do some nasty tricks with converting methods to  
blocks or use simply “eval” or “module\_eval” with a string.

HTH  
R.

---

<div class="post-metadata">

**Author:** ![raubarede](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/d07c76/32.png) [@raubarede](https://www.ruby-forum.com/u/raubarede)\
**Post date:** [June 3, 2010, 6:22pm UTC](https://www.ruby-forum.com/t/dynamicaly-define-a-method-which-body-can-contain-yield/189583/3 "2010-06-03T18:22:30Z")

</div>

Robert D. wrote:

> in 1.8. you have to do some nasty tricks with converting methods to  
> blocks or use simply “eval” or “module\_eval” with a string.

I try actualy with 1.9, but no solution by the way …

---

<div class="post-metadata">

**Author:** ![raubarede](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/d07c76/32.png) [@raubarede](https://www.ruby-forum.com/u/raubarede)\
**Post date:** [June 3, 2010, 7:01pm UTC](https://www.ruby-forum.com/t/dynamicaly-define-a-method-which-body-can-contain-yield/189583/4 "2010-06-03T19:01:11Z")

</div>

On Thu, Jun 3, 2010 at 6:22 PM, Regis d’Aubarede  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Robert D. wrote:
> 
> > in 1.8. you have to do some nasty tricks with converting methods to  
> > blocks or use simply “eval” or “module\_eval” with a string.
> 
> ## I try actualy with 1.9, but no solution by the way …

ok my bad, you call yield in the “client” block, that cannot work, let  
us look at what yield really is

def implicit  
yield # invoke the block provided by the client  
end

def explicit &blk  
blk[] # or blk.call, here it is clearer  
end

now on the client side

implicit{ yield } # what shall be invoked here???

obviously  
explicit{ blk[] }  
cannot work as blk is the block you provide here, right.

Does this make your problem clearer?

HTH  
R.

now if you call ex

---

<div class="post-metadata">

**Author:** ![raubarede](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/d07c76/32.png) [@raubarede](https://www.ruby-forum.com/u/raubarede)\
**Post date:** [June 3, 2010, 8:28pm UTC](https://www.ruby-forum.com/t/dynamicaly-define-a-method-which-body-can-contain-yield/189583/5 "2010-06-03T20:28:54Z")

</div>

Here a (partial) solution :

class B  
def p1 ; puts “p1”; end

def self.add\_tag(name,&blk)  
define\_method(name) do |\*args,&blocs|  
instance\_eval { blk.call(\*args,&blocs) }  
end  
end

end

b=B.new  
b.instance\_eval {  
B.add\_tag(“p5”) { |\*a,&bb| p1 ; bb.call(\*a) ; p1 }  
}

b.p5(1,2,3) {|\*a| puts “in bloc p5 : #{a.inspect}” }

> p1  
> in bloc p5 : [1, 2, 3]  
> p1

‘b.instance\_eval’ seem necessary for that p1() call in add\_tag() bloc  
bind  
to ‘b’ instance

Thank you ,
