2010-06-06 106 views
7

a是不確定的,那麼a || 1將拋出一個錯誤,但a = a || 1不會。這是不是有點不一致?爲什麼在Ruby中,|| 1在未定義a時會引發錯誤,但a = a || 1不會?

irb(main):001:0> a 
NameError: undefined local variable or method 'a' for main:Object 
     from (irb):1 
     from c:/ruby/bin/irb:12:in '<main>' 

irb(main):002:0> a || 1 
NameError: undefined local variable or method 'a' for main:Object 
     from (irb):2 
     from c:/ruby/bin/irb:12:in '<main>' 

irb(main):003:0> a = a || 1 
=> 1 
+0

重複http://stackoverflow.com/questions/1462407/ruby-edge-cases的 – 2010-06-06 23:20:52

回答

9
a 

在這裏,你正在評估a,這是沒有定義。因此,你會得到一個異常。

a || 1 

在這裏,你仍然必須評估a確定布爾表達式的值。就像上面一樣,a沒有定義。因此,你會得到一個異常。

a = a || 1 

這裏,a是定義。它被定義爲一個未初始化的局部變量。在Ruby中,未初始化的變量計算爲nil,因此賦值表達式的右側計算結果爲nil || 1,計算結果爲1,因此賦值表達式的返回值爲1,副作用爲a初始化爲1

編輯:似乎有當變量得到定義,當他們在Ruby中得到初始化上有些混亂。在解析時間定義的獲得,但在運行時初始化。您可以在此處看到:

foo # => NameError: undefined local variable or method `foo' for main:Object 

foo未定義。

if false 
    foo = 'This will never get executed' 
end 

此時,foo被定義,即使該行永遠不會被執行。線從未被執行的事實是完全不相關的,因爲解釋器無論如何都與此無關:局部變量由解析器定義,並且解析器顯然看到了這一行。

foo # => nil 

沒有錯誤,因爲foo定義,它的計算結果爲nil,因爲它是未初始化。

+0

+1,但我想說「它被定義爲未初始化的局部變量」。有點混亂。當你做'var = expr'時,你沒有定義'var'被初始化。你將var定義爲'expr'的值。只是'expr'評估時,'var'恰好是未初始化的,這意味着'expr'內'var'的任何引用都將評估爲零。 – sepp2k 2010-06-06 09:50:08

+1

@ sepp2k:他們是兩個非常獨立的步驟。變量定義發生在解析器中,在解釋器中初始化。根據Ruby的實現,這兩個事件之間可能會有相當長的時間。例如,在BlueRuby中,當你安裝一個Ruby程序時,Ruby源代碼被解析成BRIL(BlueRuby中間語言),然後存儲在數據庫中。它可能是*年*,直到有人真正運行程序。所有這些時間,變量都已定義,但未初始化。這兩件事情甚至可能發生在不同的機器上。 – 2010-06-06 10:26:36

1

當你做a || 1,你問它來尋找的a其價值是不確定的。

當你做a = a || 1你要它尋找aa這似乎並沒有錯誤的價值。

所以,雖然很奇怪,我不認爲它是不一致的。

+0

這是不對的。'a = a || 1'不解析爲'(a = a)|| 1'。它解析爲'a =(a || 1)',所以「賦a給a」的結果與它無關,因爲a永遠不會分配給a。 – sepp2k 2010-06-06 09:46:17

+0

@ sepp2k:我並沒有試圖暗示這一點。如果我迷惑你,我很抱歉。我相信Jörg已經更清楚地解釋了它。 – Cetra 2010-06-06 14:25:07

0

這是你的意思嗎?

if !(defined? a) then 
    a = 1 
end 

將值1聲明爲默認值可能會更簡單。

相關問題