2015-07-19 46 views
2

傳遞它的參數我回答了this問題,並偶然發現了一些奇怪的東西。 Ruby通過值傳遞參數,但變量本身是引用。因此,爲什麼第一個方法似乎通過引用傳遞其參數?爲什麼這個Ruby方法通過參考

require 'set' 
require 'benchmark' 

def add_item1!(item, list) 
    list << item unless list.include?(item) 
end 

def add_item2(item, list) 
    list |= [item] 
end 

def add_item3(item, list) 
    set = Set.new(list) 
    set << item 
    list = set.to_a 
end 

array1 = [3,2,1,4] 
add_item1!(5, array1) 
p array1 # [3, 2, 1, 4, 5] 

array2 = [3,2,1,4] 
add_item2(5, array2) 
p array2 # [3, 2, 1, 4] 

array3 = [3,2,1,4] 
add_item3(5, array3) 
p array3 # [3, 2, 1, 4] 

回答

5

非混淆術語是Call by Object-Sharing原始對象(以及複製/克隆/重複)被傳遞。

通過共享呼叫的語義從呼叫相差在於分配給該函數內起作用參數參照不可見的呼叫者

在Ruby 重新分配[本地]參數有沒有效果在呼叫者因爲它不是使用呼叫參考。

在這個示例代碼中,它清楚地顯示了而不是具有調用引用語義;或第二和第三種情況,它們分配給本地變量,否則不會修改原始對象,將像第1種那樣工作。

在'較低級別'實現是Call by Value [引用] - 也就是說,Ruby內部使用指針和whatnot - 這就是爲什麼有時使用重載短語「通過引用調用」,通常會忘記「按價值」部分......並導致這種混亂。


def add_item1!(item, list) 
    # MUTATES the list object, which is the original object passed 
    # (there is no copy/clone/duplication that occurred) 
    list << item unless list.include?(item) 
end 

def add_item2(item, list) 
    # this creates a NEW list and re-assigns it to the parameter 
    # re-assigning to a local parameter does not affect the caller 
    # the original list object is not modified 
    list |= [item] 
end 

def add_item3(item, list) 
    set = Set.new(list) 
    set << item 
    # this creates a NEW list from set and re-assigns it to the parameter 
    # re-assigning to a local parameter does not affect the caller 
    # the original list object is not modified 
    list = set.to_a 
end 
+0

我明白了,我應該用.replace修改原始對象 – peter