2017-07-26 91 views
0

我得到以下不同的結果:紅寶石塊變量範圍內/縮小方法

測試1:

def myblock 
    x = 1 
    y = 1 
    yield(x) 
    [x, y] 
end 

myblock do |x| 
y = 10 
end 
# => [1,1] 

試驗2:塊之外創建

x = 1 
y = 1 

1.upto(2) do |x| 
    y = 20 
end 
[x,y] 
# => [1,20] 

變量是可用的在塊中。他們爲什麼如此?

+1

「他們爲什麼這麼做?」 - 因爲紅寶石塊是關閉的。 – mudasobwa

+0

但是爲什麼第2塊可以改變'y'? –

回答

2

這就是如何定義局部變量的範圍。局部變量可滲透到塊中,但不會滲透到方法定義中。

+1

從技術上講還有另一個問題;在第一個片段中,沒有局部變量跨越方法定義的邊界。 – mudasobwa

1
def myblock 
    x = 1 
    y = 1 
    z = yield(x) 
    puts "y=#{y}, z=#{z}" 
    [x, y] 
end 

myblock do |x| 
y = 10 
end 
y=1, z=10 
    #=> [1, 1] 

這說明三件事是怎麼回事:

  • 塊中的y無關的myblocky。這是因爲塊中y的範圍侷限於該塊。紅寶石只能掌握該塊返回的內容,而不是內部發生的事情。
  • 塊確實返回塊中的值y,但僅僅是因爲y = 10是該塊中執行的最後一條語句。該語句的執行返回10,因此該塊返回10。如果該塊包含y = 10; 7,則會返回7
  • yield(x)的值沒有被myblock中的變量y捕獲,所以它不起作用。 。

1這是一個鮮爲人知的事實ruby實際上拍攝這些值太空。

+0

這對test1有意義,但test2怎麼樣呢?似乎「Ruby知道塊裏面發生了什麼」,所以y變成20.我是對嗎?謝謝你 –

+0

在測試2中,這是因爲'y'被定義在塊中'y'的塊是相同的'y'之前。如果你刪除了'y = 1'並且你運行了代碼(試試) –

+0

這是因爲'y'在塊之前被初始化,它在塊內部是相同的'y'。刪除'y = 1'和'[x,y]'會引發一個異常:「名稱錯誤:未定義的局部變量'y'」。它必須是塊能夠在塊計算中使用先前定義的變量的方式。這裏'y = 1.upto(2){| x | 20}'會起作用(但沒有多大意義)。 –

0

經過測試和搜索:

對於測試1,x和y是方法級局部變量和它們不共享與塊的範圍。塊中的y是一個新的局部變量(塊級)。

對於Test2,x和y是類級本地變量,它們與塊共享作用域,y中的塊仍然是外部的y(類級別)。

這都是因爲我弄亂了範圍,謝謝大家。