5

In the following, input_1 changes:

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

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

In the following, input_2 does not change:

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

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

Why does input_1 change while input_2 doesn't change?

3
  • 1
    What is your question exactly? You expect the value of input to be ['new value'] both times? Commented Jan 8, 2019 at 10:55
  • Why changes input_1 whereas input_2 doesn't change? Commented Jan 8, 2019 at 10:58
  • the concept is called "mutability". method_2 simply assignes a new variable with the same name as the other one. Commented Jan 8, 2019 at 11:00

3 Answers 3

7

It boils down to Ruby using "pass-reference-by-value".

The exact case that you encounter is described in this excellent blog post.

The gist:

In method_1 you are changing the value of an object that two different variables (input_1 and a) are both pointing to.

In method_2 you are reassigning a completely new object to one of the two variables (a).

Sign up to request clarification or add additional context in comments.

Comments

6

With a bit of simplification we can say that a variable in Ruby is a reference to a value. In your case variable a holds a reference to an array.

a << (a.append) mutates the value stored in variable a. The reference is not changed, but the value did. It's the case of method_1

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

Assignment = changes the reference stored in a variable - it starts to point to a different value. References are copied when passed to a method. Because of that when you call

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

You only change a reference stored in a that is local to the method, without any change to the reference stored in input nor to the value (and array of []) that is pointed by this reference.

1 Comment

Note that if the invocation were changed to input_2 = method_2(input_2), the new reference generated by method_2 would be assigned to input_2 since Ruby methods return the result of their last evaluation.
2

Why input_1 changes whereas input_2 doesn't change?

The very simple answer to this question is that your premise is wrong. input_1 doesn't change. The object that input_1 references changes, but that is something completely different from input_1. The name of a thing is not the same as the thing itself. (Outside of witchcraft.)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.