在方法中操作Ruby数组

5
在接下来的内容中,input_1 发生了变化:
def method_1(a)
  a << "new value"
end

input_1 = []
method_1(input_1)
input_1 #=> ["new value"]

以下内容中,input_2不会发生改变:
def method_2(a)
  a = ["new value"]
end

input_2 = []
method_2(input_2)
input_2 #=> []

为什么input_1会改变而input_2不会改变?


1
你的问题是什么?你期望输入值两次都是 ['new value'] 吗? - Alexander Presber
为什么更改了input_1,而input_2没有改变? - danieljacky
这个概念被称为“可变性(mutability)”。method_2仅仅是用与另一个变量相同的名称赋值了一个新变量。 - max pleaner
3个回答

7
这归结于Ruby使用了“按值传递引用”的方式。
你遇到的确切情况在这篇优秀的博客文章中有所描述。
要点如下:
method_1中,您正在更改两个不同变量(input_1a)都指向的对象的值。
method_2中,您正在将一个全新的对象重新分配给其中一个变量(a)。

6

简单来说,在 Ruby 中,变量是值的引用。在你的情况下,变量 a 持有一个数组的引用。

a <<a.append)会改变存储在变量 a 中的。引用没有改变,但是值已经改变了。这就是 method_1 的情况。

def method_1(a)
    a << "new value"
end

赋值=会改变变量中存储的引用,使其指向不同的值。当引用传递给方法时,引用会被复制。因此,在调用时

def method_2(a)
    a = ["new value"]
end
input = []
method_2(a)

你只是改变了存储在方法中的本地变量 a 中的引用,而没有改变存储在 input 中的引用或指向该引用的值(和数组[])。


1
请注意,如果调用更改为 input_2 = method_2(input_2),则由 method_2 生成的新引用将分配给 input_2,因为 Ruby 方法返回其最后一次评估的结果。 - pjs

2
为什么input_1会改变而input_2不会改变?
这个问题的非常简单的答案是,你的前提是错误的。 input_1 没有改变。 input_1 引用的对象 改变了,但这是与 input_1 完全不同的东西。 一件事物的名称和它本身是不同的。(除了巫术之外)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接