Is it possible to make yield keyword work inside a block given to define_method? Simple example:
class Test
define_method :test do |&b|
puts b # => #<Proc:...>
yield
end
end
Test.new.test {
puts "Hi!"
}
This code produces following error in both Ruby 1.8.7 and 1.9.0:
test.rb:4:in `test': no block given (LocalJumpError) from test.rb:8
The strange thing is the b block variable != nil
but block_given?
returns false. Is it intentional Ruby behaviour not to recognize blocks by Proc objects?
Edit: Regards to Beerlington's answer: b.call()
is is not what I am looking for. Block variable was used only to indicate that block is actually given, and is not detected inside define_method.
yield
instead of block.call
I am willing to write some extension to the way how new classes are defined in Ruby, thus any code You can write in pure Ruby should be accepted when I use my extension.
So similar semantics cannot be taken into consideration, because this forces users of my library to use only one proper way to pass a block. This breaks the TIMTOWTDI rule, and does not make my library transparent.
Code below can be simplified to code above since my_def
uses define_method
:
require 'my_library'
class Test
# client can write 'my_def' instead of 'def' since
# my_library extends Class class
my_def :test, "some parameter" do
yield # oh no, error :(
end
end
Test.new.test {
puts "Hi!"
}
I think this is what you're looking for:
class Test
define_method :test do |&b|
b.call
end
end
Test.new.test {
puts "Hi!"
}
More at http://coderrr.wordpress.com/2008/10/29/using-define_method-with-blocks-in-ruby-18/
You cannot use yield
inside a define_method
block. This is because blocks are captured by closures, observe:
def hello
define_singleton_method(:bye) { yield }
end
hello { puts "hello!" }
bye { puts "bye!" } #=> "hello!"
I don't think your users will mind not being able to use 'yield' in the way you state ---- the syntax is nothing like ordinary Ruby method definition syntax so there is unlikely to be any confusion.
More information on why you cannot pass blocks implicitly to methods found here: http://banisterfiend.wordpress.com/2010/11/06/behavior-of-yield-in-define_method/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With