2010-11-11 43 views
47

在這個例子中,我不理解紅寶石本地作用域

def foo(x) 
    if(x > 5) 
    bar = 100 
    end 
    puts bar 
end 

然後FOO(6)輸出:100 和Foo(3)輸出什麼。

但是,如果我改變了定義

def foo(x) 
    if(x > 5) 
    bar = 100 
    end 
    puts bob 
end 

我得到一個「未定義的局部變量或方法」錯誤。

所以我的問題是爲什麼我沒有得到這個錯誤,當我打電話富(3)和酒吧從未設置?

回答

53

有一些事情在這裏發生。首先,在if塊內聲明的變量與在方法頂層聲明的變量具有相同的局部範圍,這就是爲什麼barif之外可用。其次,你會得到那個錯誤,因爲bob被直接引用。 Ruby解釋器從來沒有見過它,從來沒有見過它初始化之前。但是,它在if語句之前已經初始化了bar。所以什麼時候開始禁止它知道它存在。結合這兩個,這就是你的答案。

+2

謝謝,是的,我明白在哪裏bob錯誤就是不知道爲什麼我沒有得到一個酒吧錯誤。你知道我能否依靠這種行爲,它是否是規範的一部分?例如,我可以在if語句之後檢查bar是否爲零,還是應該在if語句之前顯式聲明bar = nil? – rebo 2010-11-11 13:55:57

+1

是的,這是可靠的行爲。聲明bar = nil肯定會更明確。但我不知道大多數紅寶石主義者會這樣做。如果你將自己的方法縮小,就不應該很難理解,或者看到酒吧來自哪裏。 – Todd 2010-11-11 14:28:23

0

我不確定你在問什麼。運行foo(3)與第二個定義將始終給出錯誤,因爲bob永遠不會被定義。該方法的參數不會改變這一點。

3

所以不要把它當做福音(因爲它更多的是基於觀察和理解),但是它似乎像紅寶石解釋器會在等號的左邊標記任何單詞(沒有在它前面的印記)簽署爲本地。你的例子很奇怪,這是更奇怪的

def foo 
    bar = bar 
    puts bar // nil, which gets coerced into "" 
end 

我不明白爲什麼或如何工作,但你有它。

+1

+1! JavaScript以同樣的方式工作。它將所有聲明移至頂部並保留它們所在的分配。這可能有點混亂。 – jwueller 2010-11-11 13:47:44

+2

分配的LHS上的所有內容都將初始化爲零:'>> if false; test = whatever;結束 ;測試#=> nil'。這也是'x || = 5'的工作原理,因爲它意味着'x = x || 5'將會是'x = nil || 5',以防x先前未被定義。 – 2010-11-11 15:56:51

+0

@jwueller Ruby不會將所有分配移動到頂端。 '放下b; b = b;'結果爲 'NameError:undefined局部變量或方法'b'for main:Object'' – Ajedi32 2015-01-20 19:45:49

14

你的第二個例子實際上是一個紅鯡魚:你得到一個異常的原因不是因爲bob未初始化,這是因爲它是不明確的。無法判斷它是變量還是方法。

您的第一個示例有效,因爲未初始化的局部變量(以及全局變量和實例變量)計算爲nil。因此,puts bar是完全正確的:在一種情況下,bar初始化爲100,並且此評估爲100,在另一種情況下,它未初始化並因此評估爲nilputs在它的參數上調用to_s,它的參數是nil(它只是返回空字符串),所以一切都很好,很花哨。

參見In Ruby, why after starting irb, foo.nil? says undefined error, and @foo.nil? gives 「true」, and @@wah.nil? gives error again?

+0

我不知道Ruby,但如果這是正確的,那麼Todd接受的答案可能是不正確的。他暗示bob的問題不是它沒有,而是它沒有初始化。其他答案表明你是正確的。 – mickeyf 2012-03-26 23:47:53

+0

@Jörg:非常感謝,現在你對我很清楚。我想知道馬茨是否太忙,不能像你現在解釋的那樣清楚自己。很好的答案! – 2013-01-10 14:22:31

2

foo(3)不輸出什麼。它輸出一個換行符。

使用inspect會給你更多的是暗示:

def foo(x) 
    if(x > 5) 
    bar = 100 
    end 
    puts bar.inspect 
end 

foo(3) 

打印出

nil 

bar是一個不折不扣的變量,這恰好有nil值。