为什么这个 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]
不会造成混淆的术语是 Call by Object-Sharing:原始 对象(并且不是 copy/clone/duplicate) 通过。
The semantics of call by sharing differ from call by reference in that assignments to function arguments within the function aren't visible to the caller
在 Ruby 中 重新分配 [local] 参数 对调用方 没有影响 [=21] =]不使用引用调用。
在此示例代码中,显然不具有按引用调用语义;或第二种和第三种情况,它们分配回 local 变量,但除此之外 不修改原始对象 ,将像第一种情况一样工作。
在 'lower level' 上,实现是按 [引用] 的值调用 - 也就是说,内部 Ruby 使用指针和诸如此类的东西 - 这就是为什么有时重载短语 "call by reference"被使用,经常忘记 "by value" 部分 .. 并导致这种混淆。
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
我回答了
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]
不会造成混淆的术语是 Call by Object-Sharing:原始 对象(并且不是 copy/clone/duplicate) 通过。
The semantics of call by sharing differ from call by reference in that assignments to function arguments within the function aren't visible to the caller
在 Ruby 中 重新分配 [local] 参数 对调用方 没有影响 [=21] =]不使用引用调用。
在此示例代码中,显然不具有按引用调用语义;或第二种和第三种情况,它们分配回 local 变量,但除此之外 不修改原始对象 ,将像第一种情况一样工作。
在 'lower level' 上,实现是按 [引用] 的值调用 - 也就是说,内部 Ruby 使用指针和诸如此类的东西 - 这就是为什么有时重载短语 "call by reference"被使用,经常忘记 "by value" 部分 .. 并导致这种混淆。
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