提问人:peter 提问时间:7/20/2015 最后编辑:Communitypeter 更新时间:7/20/2015 访问量:71
为什么这个 Ruby 方法通过引用传递它的参数
Why this Ruby method passes it's argument by reference
问:
我回答了这个问题,偶然发现了一些奇怪的事情。 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赞
user2864740
7/20/2015
#1
不容易混淆的术语是 Call by Object-Sharing:传递原始对象(而不是副本/克隆/重复)。
通过共享调用与通过引用调用的语义不同,因为调用方看不到函数中函数参数的赋值
在 Ruby 中,重新分配 [local] 参数对调用方没有影响,因为它不使用按引用调用。
在此示例代码中,它显然没有 Call by Reference 语义;或者第 2 种和第 3 种情况,它们赋回局部变量,但不修改原始对象,将像第 1 种情况一样工作。
在“较低级别”上,实现是按值调用 [of a reference]——也就是说,Ruby 在内部使用指针之类的东西——这就是为什么有时使用重载短语“按引用调用”,经常忘记“按值”部分。并导致这种混乱。
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赞
peter
7/20/2015
我明白了,我应该使用.replace来修改原始对象
上一个:按值传递和按名称传递的输出
下一个:Swift 会自动克隆参数吗?
评论