7

在 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)

输出:

42
Scope1
In scope1_method

这是如何以及为什么会发生的?

4

2 回答 2

4

该调用为其给出的块Proc.new创建一个闭包。在为块创建闭包时,块被绑定到Proc.new调用范围内的原始变量。

为什么这样做?

它允许 Ruby 块充当闭包。闭包非常有用,维基百科条目(上面链接)很好地解释了它们的一些应用程序。

这是怎么做到的?

这是在 Ruby VM(在 C 代码中)通过复制进入Proc.new方法之前存在的 Ruby 控制框架来完成的。然后该块在该控制帧的上下文中运行。这有效地复制了该帧中存在的所有绑定。在 Ruby 1.8 中,您可以proc_alloceval.c. 在 Ruby 1.9 中,您可以proc_newproc.c.

于 2013-03-07T22:37:10.490 回答
1

此行为是设计使然。在 Ruby 中,blocks、procs 和 lambdas 是词法闭包。阅读这篇博文,简要解释 Ruby 的三种闭包风格之间的差异。

于 2013-03-07T22:33:41.983 回答