2014-02-10 109 views
3

我正在學習ruby。我正試圖理解封閉方式的工作方式,以及它們與功能的區別。 我完全知道應該通過proc或lambda來實現閉包。瞭解Ruby嵌套函數

我想深入瞭解紅寶石。這樣我檢查各種非傳統的代碼。我想了解爲什麼第3行工作,而第5行是一個錯誤。

x=123 
def b(x) 
    p x 
    def a(u) 
     p x # why is this an error?!?!? 
    end 
    a 4 
end 

b 1 
  1. 如果不能訪問B的參數,爲什麼沒有訪問全局x = 123?
  2. 爲什麼這個工作,如果我明確地使用變化線1 & 5全球「$ x」?
  3. 爲什麼這個工作,如果我明確使用lambda?

這純粹是一個學習練習,我這樣做是爲了理解發動機罩下面發生了什麼。

回答

4

這是所謂的「範圍門」。基本上,當你開始定義一個方法/類/模塊時,會創建一個新的作用域,並且不能訪問來自其他作用域的所有局部變量。這不適用於實例/全局變量,您將繼續訪問這些變量。

由於lambda不是一種方法,它不會創建新的作用域,而是重新使用現有的作用域。

此外,

爲什麼3個線工程

x = 123 
def b(x) 
    p x # this "x" is "x the parameter", not "x the local variable from outer scope" 
     # that's why it works. If you tried to access the local var, it wouldn't work. 
    def a(u) 
     p x # like here, see? Doesn't work. 
    end 
    a 4 
end 

b 1 
3

首先要明白的是,def不會做一個 「函數」(這是什麼,即使是在Ruby中是什麼意思?) - def在某個對象或類上定義了一個方法。即使它看起來不在任何對象內部,它仍然在「主」對象上定義了一個方法。所以當你做def a時,它對方法b不是「本地」的;它是一種方法a,就像您在頂層定義它一樣,除非它在b運行之前沒有被定義。它可以被稱爲來自其他地方的方法a。你有嵌套方法定義

因爲它是爲了限定方法,其中大部分的時間在一個類或模塊的頂部電平被定義,def未曾被做捕捉外部變量。

+0

出於好奇,如果b是屬於某個類的方法,會發生什麼?一個也屬於那個班? – eshalev

+0

@eshalev:是的。 (但'a'只會在'b'第一次運行後定義(需要運行'def'語句來定義方法)) – newacct