I'm trying to run this code, to overwrite each
for an Array instance:
my_array.define_singleton_method(:each, &block) do
super { |x| x.instance_exec(&block) }
end
The problem is I get this error both block arg and actual block given (SyntaxError)
, because I'm giving two block arguments to define_singleton_method
How can I redefine each
while using each
's block, if I need a block for the method definition?
Your your issue is the passing of &block
as an explicit argument to define_singleton_method
and also passing an implicit block.
What you actually want to do is capture &block
as an argument to your new each
method so that you can pass that block forward.
Essentially define_singleton_method
looks like this:
define_singleton_method(method_name) {|method_arguments| }
So you can accomplish your goal as follows:
my_array = [1,2,3]
my_array.define_singleton_method(:each) do |&block|
puts 'new each'
super(&block)
end
my_array.each {|i| puts i * 2}
# new each
# 2
# 4
# 6
#=> [1,2,3]
This is essentially the same as
def my_array.each(&block)
puts 'new each'
super
end
# or even
def my_array.each
puts 'new each'
super
end
The only difference is def...end
method declaration allows for implicit argument passing, as shown, whereas define_singleton_method
does not, so we must capture the block and explicitly pass it to super
.