2016-01-25 26 views
-2

在下面的代碼,a被的times外部初始化,但times創建內部範圍,並a是可訪問的:局部變量時的方法和方法調用變量

a = 5 
3.times do |n| 
    a = 3 
end 
a # => 3 

a返回值是3因爲a可從3.times do ... end創建的範圍中獲得,該範圍允許重新分配a的值。實際上,它重新分配了a3三次。

爲什麼以下不同?

a = 5 
def adder(num) 
    num = 3 
end 
adder(a) # => 3 
a # => 5 

這是因爲我們在a帶來的,但它不會改變局部變量,也許是因爲它的方法。我不知道。爲什麼是a5而不是3

+0

爲什麼你的方法叫'加法器'?它不添加任何東西。 – Stefan

+0

對不起,我只是想弄清範圍規則。無視愚蠢的方法名稱,我認爲我理解ruby中的範圍規則,但我認爲自己很困惑。規則對我來說並不清楚。 在第一個例子中a = 3,因爲塊中存在範圍泄漏?還是因爲a = 3重新分配? 然後在第二個例子中,在末尾做了一個=> 5,因爲變量是通過值而不是通過引用傳遞給方法的?如果在方法內部有一個<<操作會影響a的值,那該怎麼辦?它很混亂 –

+0

您可以通過其方法修改(變更)傳遞的對象,例如, 'array << element'。但是你不能從一個方法內重新分配外部作用域的變量。試圖這樣做只會在方法的內部作用域中創建一個局部變量。請參閱https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing – Stefan

回答

2

沒有字形的所有Ruby變量(@,@@, $)對於當前方法,模塊,類或當前程序都是本地的。

a = 5 # local to program 

def adder 
    # local to method 
    num = 3 
    puts num 
end 
adder(1) 
# => 3 

module Foo 
    # local to module 
    num = 2 
    puts num 
end 
# => 2 

class Bar 
    # local to class 
    num = 1 
    puts num 
end 
# => 1 

a  # local to program 
# => 5 

在這些變量中,變量被限定在引入它們的塊中,正如您自己所注意的那樣。

0

爲什麼a 5而不是3?

a = 5 
def adder(num) 
    num = 3 
end 
adder(a) # => 3 
a # => 5 

因爲當你調用addera,它是pass by value。所以當num的值改變時,它不會改變a的值。

如果你想a改變價值,你需要做a = adder(a)

+0

確定這是有道理的,所以可以說這個方法被賦予了一個數組作爲參數,並且我們使用方法內的<<修改了該數組。那麼這會改變這個變量是否正確?所以如果我稍後再次要求這個數組,它的值將會改變,因爲現在我們改變了這個數組。它通過引用而不是值傳遞。是對的嗎? –

+1

「那麼這會改變這個變量是否正確?」 - 不,它會改變變量*指向*的*數組*。它會*變異變量。 「所以如果我稍後再問這個數組,那麼從現在我們突變數組開始,它的值就會改變。」 - 對,就是這樣。因爲你突變了* array *,* not *因爲你突變了變量。你不能通過方法調用來變換變量('<<僅僅是一個方法調用),* only *只能賦值。 ...「 –

+1

...」正在通過引用傳遞不值。「 - 沒有。在Ruby中,所有東西總是被價值傳遞。當你使用'<<'變異數組時,你正在改變數組。你*不*改變變量。變量仍指向與之前完全相同的對象。只是對象具有不同的內部狀態。這與通過引用無關。這只是可變的狀態。 Ruby不是一種純粹的函數式語言,你可以改變對象的狀態。 –

1

你的兩個例子是不一樣的。第一個是用塊調用方法。塊是關閉,這意味着它們記住它們在其中定義的上下文(特別是保留對該範圍內的變量的引用)。第二個是定義。這不是封閉。事實上,這是所謂的「範圍門」。這意味着當一個方法(/類/模塊)的定義開始時,所有先前已知的局部變量被推出範圍。所以,如果您要從adder內部訪問a,您將獲得NameError

而且,正如@Atri指出的那樣,您的方法定義沒有像您期望的那樣工作的機會。你甚至不會在那裏指定a。那麼你如何期待a改變?