爲什麼下面的代碼不會引發錯誤?爲什麼我可以引用一個if/unless/case語句之外的變量?
if false
x = 0
end
x #=> nil
而下面確實引發錯誤:
y # NameError: undefined local variable or method `x' for main:Object
同樣的事情發生與unless
& case
語句。
爲什麼下面的代碼不會引發錯誤?爲什麼我可以引用一個if/unless/case語句之外的變量?
if false
x = 0
end
x #=> nil
而下面確實引發錯誤:
y # NameError: undefined local variable or method `x' for main:Object
同樣的事情發生與unless
& case
語句。
這是因爲Ruby解析器的工作原理。變量由解析器定義,解析器逐行遍歷代碼,而不管它是否會被實際執行。
一旦解析器看到x =
,它就會在當前範圍內定義本地變量x
(值爲nil
)。由於if
/unless
/case
/for
/while
不會創建新的示波器,因此x
已在代碼塊外定義並可用。並且由於內部塊從未被評估爲條件爲假,所以x
未被分配給(並且因此是nil
)。
這裏有一個類似的例子:
defined?(x) and x = 0
x #=> nil
請注意,這是發生了什麼相當高層次的概述,而不一定究竟是如何解析的作品。
這與Ruby的範圍規則的怪癖有關。
在ruby中,一個不帶變量的變量x
本身可以是局部變量或方法調用 - 語法不能分辨哪個變量。由解析器解析局部變量引用,由解析器決定。規則很簡單:如果已經在本地範圍中看到對同名變量的分配,則引用是局部變量,並且引用被綁定到該局部變量。否則,這是一個方法調用,它將在運行時被查找。
Ruby中的局部變量引用在數組查找中進行了優化(每個局部變量都分配了一個'slot',並且分析器生成的綁定局部變量引用被轉換爲槽引用)。該陣列被初始化爲所有nil
:
/* initialize local variables */
for (i=0; i < local_size; i++) {
*sp++ = Qnil;
}
因此,如果你指的是沒有被分配的局部變量,通過一個綁定本地引用(如果有基準上述跳過的分配只能發生在相同的本地範圍內),您將獲得nil
。
我覺得你的問題很有意思,所以我想看看它,並發現這一點: I don't understand ruby local scope
正確的答案似乎是把約爾格。
讓我們看看會發生什麼,當您嘗試訪問未初始化的變量:
NameError: undefined local variable or method `UNDECLAREDVAR' for main:Object
的異常狀態,這是無法評估是否變量或方法。它不拋出相同異常的原因是因爲未初始化的局部變量被設置爲nil。所以puts x
是好的,因爲口譯員知道x
是可變的但未初始化,而不是一種方法。
啊,打我吧。很好的解釋。 – nneonneo