From: Regis d'Aubarede on
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!

Attachments:
http://www.ruby-forum.com/attachment/4772/essai.rb

--
Posted via http://www.ruby-forum.com/.

From: Robert Dober on
On Thu, Jun 3, 2010 at 3:28 PM, Regis d'Aubarede
<regis.aubarede(a)gmail.com> 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.

From: Regis d'Aubarede on
Robert Dober 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 ...
--
Posted via http://www.ruby-forum.com/.

From: Robert Dober on
On Thu, Jun 3, 2010 at 6:22 PM, Regis d'Aubarede
<regis.aubarede(a)gmail.com> wrote:
> Robert Dober 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
> Posted via http://www.ruby-forum.com/.
>
>



--
The best way to predict the future is to invent it.
-- Alan Kay

From: Regis d'Aubarede on
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 ,
--
Posted via http://www.ruby-forum.com/.