范围令人困惑

问题描述

| 我对块内变量的范围感到困惑。这有效:
f = \'new\'
[1,2,3].each do |n| puts f * n end
#=> new newnew newnewnew
但这不是:
[1,3].each do |n|
  a ||=[]
  a << n
end
a
#=>a does not exsit!
为什么是这样?并请为我提供一些有关此主题的资源。     

解决方法

        什么令人困惑? 在第一个代码段中,创建了ѭ2and,然后执行了
each
块,该块可以看到自身之外的东西(称为封闭范围)。这样就可以看到
f
。 在第二个代码段中,您在块内创建了“ 5”,因此其范围就是该块。在块外,ѭ5不存在。 当您引用一个名称(例如,ѭ5)时,ruby将从当前作用域向外移动,在所有封闭的作用域中查找该名称。如果在封闭的范围之一中找到它,则使用与名称关联的值。如果没有,它将返回到最本地的作用域并在其中创建名称。随后的名称查找将产生与该名称相关的值。 当一个块结束时,该范围内的名称会丢失(值不会丢失,而只会丢失名称;当垃圾收集器看到没有更多的名称(或其他任何东西)引用该值时,值会丢失)。 gc收集值以重新使用其内存)。 如果可视化是您的事,我发现将范围视为阶梯很有帮助,并且在程序开始时,您站在最重要的第一步。每次输入一个块时,都将下一个步骤。您可以看到当前步骤中的所有内容,以及正在执行的步骤之上的所有步骤,但是在下面的步骤中则看不到任何东西。当您引用变量名称时,您会四处寻找找到它的步骤。看到它时,就使用该值。如果看不到它,请查看正在执行的操作上方的下一步。如果看到它,则使用该值。您要一遍又一遍地执行此操作,直到您查看了最顶层的步骤,但看不到该名称。如果发生这种情况,请在站立的步骤上创建名称(如果正在查找分配的名称,请给它一个值)。下次寻找该名称时,您会在站立的步骤中看到该名称,并在那里使用它。 街区结束时,您要上一个台阶。由于在下面的步骤中看不到任何名称,因此先前使用的步骤中的所有名称都将丢失。 如果您有帮助,请以这种方式考虑。如果没有,那就不要。 1实际上,您处于第二步,因为您不在全局范围内,但要使用全局范围内的名称,则必须在名称开头使用$。因此,在楼梯示例中,如果要查找的名称开头有$,则直接在最上面查找。如果没有,您看起来不会那么远。但是,这是错误的,因为程序中的所有楼梯都将共享相同的第一步,这很奇怪。     ,        地图效果更好:
a = [1,2,3].map do |n|
  n
end
无需在块外声明“ 5”。     ,        很简单,在块内定义的变量在外部是不可见的(如果发生这种情况,我们会说该变量已泄漏,并且正如该词暗示的那样,这将是不好的):
>> lambda { x = 1 }.call
=> 1
>> x
NameError: undefined local variable or method `x\' for main:Object