In Ruby, procs seem to have access to local variables that were present at the time they were declared, even if they are executed in a different scope:
在Ruby中,procs似乎可以访问声明它们时出现的局部变量,即使它们在不同的范围内执行:
module Scope1
def self.scope1_method
puts "In scope1_method"
end
end
module Scope2
def self.get_proc
x = 42
Proc.new do
puts x
puts self
scope1_method
end
end
end
Scope1.instance_eval(&Scope2.get_proc)
Output:
42
Scope1
In scope1_method
How and why does this occur?
这是怎么发生的?
2 个解决方案
#1
4
The Proc.new
call creates a closure for the block that it's given. In creating a closure for the block, the block is bound to the original variables in the scope of the Proc.new
call.
Proc.new调用为它给出的块创建一个闭包。在为块创建闭包时,块绑定到Proc.new调用范围内的原始变量。
Why is this done?
It allows Ruby blocks to function as closures. Closures are extremely useful, and the Wikipedia entry (linked above) does an excellent job of explaining some of their applications.
它允许Ruby块作为闭包。闭包非常有用,*条目(上面链接)在解释他们的一些应用程序方面表现非常出色。
How is this done?
This is done in the Ruby VM (in C code) by copying the Ruby control frame that exists before entering the Proc.new
method. The block is then run in the context of this control frame. This effectively copies all of the bindings that are present in this frame. In Ruby 1.8, you can find the code for this in the proc_alloc
function in eval.c
. In Ruby 1.9, you can find this in the proc_new
function in proc.c
.
这是通过在进入Proc.new方法之前复制存在的Ruby控件框架在Ruby VM(在C代码中)完成的。然后在该控制帧的上下文中运行该块。这有效地复制了此框架中存在的所有绑定。在Ruby 1.8中,您可以在eval.c的proc_alloc函数中找到相应的代码。在Ruby 1.9中,您可以在proc.c中的proc_new函数中找到它。
#2
1
This behavior is by design. In Ruby, blocks, procs, and lambdas are lexical closures. Read this blog post for a short explanation of the differences between Ruby's three flavors of closure.
此行为是设计使然。在Ruby中,blocks,procs和lambdas是词法闭包。阅读这篇博文,简要介绍Ruby的三种封闭方式之间的差异。
#1
4
The Proc.new
call creates a closure for the block that it's given. In creating a closure for the block, the block is bound to the original variables in the scope of the Proc.new
call.
Proc.new调用为它给出的块创建一个闭包。在为块创建闭包时,块绑定到Proc.new调用范围内的原始变量。
Why is this done?
It allows Ruby blocks to function as closures. Closures are extremely useful, and the Wikipedia entry (linked above) does an excellent job of explaining some of their applications.
它允许Ruby块作为闭包。闭包非常有用,*条目(上面链接)在解释他们的一些应用程序方面表现非常出色。
How is this done?
This is done in the Ruby VM (in C code) by copying the Ruby control frame that exists before entering the Proc.new
method. The block is then run in the context of this control frame. This effectively copies all of the bindings that are present in this frame. In Ruby 1.8, you can find the code for this in the proc_alloc
function in eval.c
. In Ruby 1.9, you can find this in the proc_new
function in proc.c
.
这是通过在进入Proc.new方法之前复制存在的Ruby控件框架在Ruby VM(在C代码中)完成的。然后在该控制帧的上下文中运行该块。这有效地复制了此框架中存在的所有绑定。在Ruby 1.8中,您可以在eval.c的proc_alloc函数中找到相应的代码。在Ruby 1.9中,您可以在proc.c中的proc_new函数中找到它。
#2
1
This behavior is by design. In Ruby, blocks, procs, and lambdas are lexical closures. Read this blog post for a short explanation of the differences between Ruby's three flavors of closure.
此行为是设计使然。在Ruby中,blocks,procs和lambdas是词法闭包。阅读这篇博文,简要介绍Ruby的三种封闭方式之间的差异。