理解 Ruby 嵌套函数

esh*_*lev 4 ruby closures

我现在正在学习 ruby​​。我试图了解闭包的工作方式,以及它们与函数的不同之处。我完全知道应该通过 proc 或 lambda 实现闭包

我试图深入了解红宝石。因此,我检查了各种非正统的代码。我试图理解为什么第 3 行有效而第 5 行是错误的。

x=123
def b(x)
    p x
    def a(u)
      p x # why is this an error?!?!?
    end
    a 4
end

b 1
Run Code Online (Sandbox Code Playgroud)
  1. 如果a不能访问b的参数,为什么不能访问全局x=123?
  2. 如果我明确地将第 1 行和第 5 行更改为全局“$x”,为什么这会起作用?
  3. 如果我明确使用 lambda,为什么这会起作用?

这纯粹是一个学习练习,我这样做是为了了解幕后发生的事情。

Ser*_*sev 7

这就是所谓的“范围门”。基本上,当您开始定义方法/类/模块时,会创建一个新作用域,并且无法访问其他作用域中的所有局部变量。这不适用于实例/全局变量,您将保留对它们的访问权限。

由于 lambda 不是一种方法,因此它不会创建新的作用域,而是重用现有的作用域。

还,

为什么3号线可以运行

x = 123
def b(x)
    p x # this "x" is "x the parameter", not "x the local variable from outer scope"
        # that's why it works. If you tried to access the local var, it wouldn't work.
    def a(u)
      p x # like here, see? Doesn't work.
    end
    a 4
end

b 1
Run Code Online (Sandbox Code Playgroud)


new*_*cct 5

首先要理解的是,def它并没有创建一个“函数”(这在 Ruby 中意味着什么?)——在某个对象或类上def定义一个方法。即使它看起来不在任何对象内部,它仍然在“主”对象上定义了一个方法。因此,当您这样做时def a,它不是该方法的“本地” b;它是一种方法a,就像您在顶层定义它一样,只是它在b运行之前不会被定义。它可以作为a其他地方的方法调用。您有嵌套的方法定义

因为它是用来定义方法的,大多数时候是在类或模块的顶层定义的,def从来没有用来捕获外部变量。