Reputation: 5745
Why am I getting an error:
LocalJumpError
# ~> no block given (yield)
module M
def hello(text = 'bba')
puts "yo-#{text}" # => nil
end # => :hello
instance_methods # => [:hello]
m = instance_method(:hello) # => #<UnboundMethod: M#hello>
define_method(:bye) do |*args, &block|
yield # ~> LocalJumpError: no block given (yield)
m.bind(self).(*args, &block)
end # => :bye
end # => :bye
class A
include M # => A
end # => A
A.new.hello('vv') # => nil
A.new.bye('zz') do |p| # => #<A:0x00007fa8c401e090>
puts "ggg"
end
# >> yo-vv
# ~> LocalJumpError
# ~> no block given (yield)
Upvotes: 1
Views: 179
Reputation: 198324
It's the difference in the semantics of def
and define_method
. See this:
module M
def outer(&block)
puts "outer: #{yield}"
def inner1
puts "inner1: #{yield}"
end
M.define_method(:inner2) do
puts "inner2: #{yield}"
end
M.define_method(:inner3) do |&block|
puts "inner3: #{block.call}"
end
inner1 { 1 }
inner2 { 2 }
inner3 { 3 }
end
end
class A
include M
end
A.new.outer { 0 }
# => outer: 0
# inner1: 1
# inner2: 0 (!!!)
# inner3: 3
yield
only works inside def
.
Thus, inner1
calls its own block; but inner2
uses the block of the def
it is in. The correct way to invoke the block inside define_method
is to capture it in the parameter list (as you did), and then use #call
or #[]
on it, like inner3
demonstrates.
In your code, there is no def
around, thus no block is available when you yield
. You can use the above method, and replace yield
with block.call
.
Upvotes: 4