如何给define_singleton_method传两个块?重定义each方法遇语法错误
重定义Array实例each方法的块参数问题解决
问题描述
尝试通过以下代码重定义Array实例的each方法:
my_array.define_singleton_method(:each, &block) do super { |x| x.instance_exec(&block) } end
执行后触发语法错误:both block arg and actual block given (SyntaxError),核心原因是define_singleton_method被同时传入了块参数(&block)和方法定义体的块(do...end),Ruby不允许这种双重块传递的写法。
解决方案
要实现重定义each并正确处理外部传入的块,需要调整块的捕获方式,避免和define_singleton_method的参数冲突,以下是两种可行写法:
写法一:在方法参数列表中捕获块
my_array.define_singleton_method(:each) do |&block| super { |x| x.instance_exec(&block) } end
将&block放在方法定义的参数列表内(do |&block|),这样就能直接捕获调用each时传入的块,再通过super调用原Array#each逻辑,在其内部块中用x.instance_exec(&block)让数组元素作为上下文执行捕获到的块。
写法二:用Proc.new在方法内部捕获块
my_array.define_singleton_method(:each) do block = Proc.new super { |x| x.instance_exec(&block) } end
当方法被调用且带有块时,Proc.new会自动捕获该块,后续逻辑和写法一一致,同样能实现重定义需求。
内容的提问来源于stack exchange,提问作者Mirror318
相关产品推荐
相关产品推荐

