我很困惑塊內變量的範圍。這工作:範圍令人困惑
f = 'new'
[1,2,3].each do |n| puts f * n end
#=> new newnew newnewnew
但這並不:
[1,2,3].each do |n|
a ||=[]
a << n
end
a
#=>a does not exsit!
這是爲什麼?請爲我提供一些關於這個話題的資源。
我很困惑塊內變量的範圍。這工作:範圍令人困惑
f = 'new'
[1,2,3].each do |n| puts f * n end
#=> new newnew newnewnew
但這並不:
[1,2,3].each do |n|
a ||=[]
a << n
end
a
#=>a does not exsit!
這是爲什麼?請爲我提供一些關於這個話題的資源。
什麼讓人困惑?
在第一片斷f
被創建並隨後each
塊被執行,它可以看到外面本身的東西(稱爲封閉的範圍)。所以它可以看到f
。
在第二個片段中,您在該塊內部創建了a
,因此其範圍就是該塊。在塊之外,a
不存在。
當你引用一個名字時(例如a
),ruby將從當前作用域向外移動,查看所有封閉作用域的名稱。如果它在其中一個封閉範圍內找到它,它將使用與該名稱關聯的值。如果不是,則返回大多數本地範圍並在那裏創建名稱。隨後的名稱查找將產生與該名稱關聯的值。
塊結束時,該範圍內的名稱將丟失(值不會丟失,只是名稱;當垃圾回收器發現沒有更多名稱(或任何內容)引用時,值會丟失該值,並且gc收集該值以重用其內存)。
當一個模塊結束時,您將踏上一個臺階。由於您在下面的步驟中看不到任何名稱,因此您之前步驟中的所有名稱都會丟失。
如果這可以幫助你,那麼想一想。如果沒有,不要。
其實你在第二個步驟,因爲你在全球範圍內不是,但是從全球範圍內使用的名稱,你必須在名稱的開頭使用$。因此,在樓梯示例中,如果您要查找的名稱在開頭處具有$,則可直接查看最上面的步驟。如果沒有,你看起來不那麼遠。然而,這是錯誤的,因爲程序中的所有樓梯都會共享相同的頂級步驟,這是很奇怪的想法。
+1。這取決於範圍'a'是***第一***使用。 – 2011-06-12 17:32:42
如果我使用比喻,我會提到一輛帶煙燻玻璃的汽車;你可以從內部看到外部,但不是相反。 – sawa 2011-06-12 17:57:15
@sawa是的,但你有嵌套的範圍,這將像汽車內的汽車。然後事情開始變得混亂。 – 2011-06-12 17:58:00
很簡單,一個塊中定義的變量是不可見的外(如果發生這種情況,我們會說變量已經泄露,並作爲顧名思義,這將是壞的):
>> lambda { x = 1 }.call
=> 1
>> x
NameError: undefined local variable or method `x' for main:Object
地圖的效果要好得多:
a = [1,2,3].map do |n|
n
end
不需要聲明a
外塊。
你是對的!但我只想舉例說明我不能在範圍之外使用的變量 – mko 2011-06-14 09:45:28
@sawa感謝您再次糾正我的問題 – mko 2011-06-14 09:19:05