2013-03-12 44 views

回答

4

&foo尝试将foo作为块传递给instance_exec,并且您已经传递了显式块。忽略&符号与其他任何参数一样发送foo(除了它是一个Proc实例)。所以,试试这个来代替:

instance_exec(1,2,3,foo) do |*args, block| 
    puts *args 
    block.call 
    puts "bar" 
end 

这也意味着,你可以这样做:

bar = proc{ |*args, block| 
    puts *args 
    block.call 
    puts "bar" 
} 

instance_exec(1,2,3,foo,&bar) 

,并得到同样的结果。

更多信息以Difference between block and &block in Ruby

+2

不幸的是,这不适合我的情况。我试图以一种允许我跟踪其执行时间的方式透明地封装现有的proc。由于我无法控制我正在封装的proc的签名,因此我无法使用此方法。一般来说,这似乎是一个很好的解决方法。 – Ajedi32 2015-05-12 15:23:26

2

我大约晚了3年参加这个晚会,但是我想我会分享它可以让你把内部块更像一个真正的块中的做法,而不是只是一个普通的旧的论点。

我所知道的最好的方法是创建一个对象作为绑定上下文,并将外部块定义为方法。所以,如果我改写原来的例子如下没有instance_exec电话...

inner_proc = proc { puts "inner" } 
outer_proc = proc { |*args, &inner_block| 
    puts *args 
    inner_block.call 
    puts "bar" 
} 

我们可以定义outer_proc作为对象的方法

scope_object = Object.new 
scope_object.define_singleton_method :bound_proc, &outer_proc 

现在,您可以拨打scope_object.bound_proc代替instance_exec通话以上。

scope_object.bound_proc 1, 2, 3, &inner_proc 

您将获得:

1 
2 
3 
inner 
bar 

不幸的是,你会得到一个LocalJumpError如果您尝试以产生outer_proc内,而不是inner_block.call,我不完全知道为什么。如果有人有这个答案,那么我会感兴趣。

+0

它的工作原理!非常感谢! – benjaminchanming 2017-02-01 08:27:53