CompChemist
CompChemist

Reputation: 923

Why is insert/delete on one array modifying another as well?

I have a question about using insert and delete_at with arrays. If I insert an element into an array (arry) and then store that value in a different variable (temp), why does the variable temp change after I use delete_at on arry? Is there a way to store the value of the array with the insert object permanently?

Here is some sample code:

arry = [0,1,3,4]
# => [0, 1, 3, 4]
arry.insert(1,5)
# => [0, 5, 1, 3, 4]
temp = arry
# => [0, 5, 1, 3, 4]
arry.delete_at(1)
# => 5
temp
# => [0, 1, 3, 4]

Upvotes: 4

Views: 1309

Answers (3)

tkroman
tkroman

Reputation: 4798

I'm just feeling in a right mood to tell something more than previous commenters, because some time ago I've had nearly the same headache with all this pass-reference-by-value stuff. So:

Ruby's variables are actually references to underlying objects inside Ruby's virtual machine. They are passed into functions 'by value', which means when you do function(arg), function actually gets copy of reference to the memory object. So, function gets a valid reference to object, which arg and copy of arg reference. When you perform some actions on object referenced by arg or it's copy, you successfully modify directly that object. (But when you operate directly on references, things happen only to references, hence, copied reference inside function may even be deleted, which doesn't affect original reference or object. Consider this:

array_ref0 = [1,2,3] # actually, this reference represents array
array_ref1 = array_ref0
def f(arg); arg[0] = 0; end
f(array_ref0)
p array_ref0 # => [0,2,3]
p array_ref1 # => [0,2,3]
array_ref0 = [1,2,3]
p array_ref0 # => [1,2,3]
#but!
p array_ref1 # => [0,2,3]

That's because saying array_ref0 = [1,2,3] you reassigned the reference to a new object, but array_ref1 still references the old object, which is alive because >=1 references reference to it (not going to talk much about GC here)

def g(arg); arg = nil; end
g(array_ref0)
p array_ref0 # => [1,2,3], because we only nil-ed copy of array_ref0.

Hope that cleared things a little.

I'm not telling you to #dup your array because previous commenters gave you comprehensive practical answers.

Upvotes: 1

emre nevayeshirazi
emre nevayeshirazi

Reputation: 19241

When you assign an array to a new variable, the array itself is not copied but only reference to that array is set. If you want to save original array to new variable, you need to clone the array You can do it via dup.

temp = arry.dup

Upvotes: 6

Marek Lipka
Marek Lipka

Reputation: 51151

It happens because you make temp variable pointing at the same object as arry variable. To do what you want, you should make copy of this object:

temp = arry.dup

Upvotes: 1

Related Questions