Ruby块,过程和局部变量

时间:2013-03-07 22:18:47

标签: ruby

在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

这是如何以及为何发生的?

2 个答案:

答案 0 :(得分:4)

Proc.new调用会为其提供的块创建closure。在为块创建闭包时,块绑定到Proc.new调用范围内的原始变量。

为什么要这样做?

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

这是怎么做到的?

这是在Ruby VM(在C代码中)通过复制在进入Proc.new方法之前存在的Ruby控制框架来完成的。然后在该控制帧的上下文中运行该块。这有效地复制了此帧中存在的所有绑定。在Ruby 1.8中,您可以在proc_alloc的{​​{1}}函数中找到相应的代码。在Ruby 1.9中,您可以在eval.c中的proc_new函数中找到它。

答案 1 :(得分:1)

此行为是设计使然。在Ruby中,blocks,procs和lambdas是词法closures。阅读this blog post以简要解释Ruby的三种封闭方式之间的差异。