0

When I try to pop an element from an array, it pops. When I assign that array to another variable before popping and then if I pop, the pop operation affects both the arrays.

For example:

 ruby-1.9.2-p290 :339 > a= [1,2,3]
     => [1, 2, 3] 
    ruby-1.9.2-p290 :340 > b = a
     => [1, 2, 3] 
    ruby-1.9.2-p290 :341 > a
     => [1, 2, 3] 
    ruby-1.9.2-p290 :342 > b
     => [1, 2, 3] 
    ruby-1.9.2-p290 :343 > a.pop
     => 3 
    ruby-1.9.2-p290 :344 > a
     => [1, 2] 
    ruby-1.9.2-p290 :345 > b
     => [1, 2] #WHY?
    ruby-1.9.2-p290 :346 > x = [1,2,3]
     => [1, 2, 3] 
    ruby-1.9.2-p290 :347 > y = x
     => [1, 2, 3] 
    ruby-1.9.2-p290 :348 > z = x
     => [1, 2, 3] 
    ruby-1.9.2-p290 :349 > y
     => [1, 2, 3] 
    ruby-1.9.2-p290 :350 > z
     => [1, 2, 3] 
    ruby-1.9.2-p290 :351 > y.pop
     => 3 
    ruby-1.9.2-p290 :352 > y
     => [1, 2] 
    ruby-1.9.2-p290 :353 > z
     => [1, 2] # WHY?
    ruby-1.9.2-p290 :354 > x
     => [1, 2] 
    ruby-1.9.2-p290 :355 > 

If I use pop, all the variables are affected. How do I keep the original array and pop from the other one only?

0

3 Answers 3

6

If you assign an array to a new variable, it's not copied, but you only set a reference to the original array. If you want to keep the original array, you have to clone it by using dup:

ruby-1.9.2-p180 :001 > a = [1,2,3]
 => [1, 2, 3] 
ruby-1.9.2-p180 :002 > b = a.dup
 => [1, 2, 3] 
ruby-1.9.2-p180 :003 > b.pop
 => 3 
ruby-1.9.2-p180 :004 > a
 => [1, 2, 3] 
ruby-1.9.2-p180 :005 > b
 => [1, 2] 
Sign up to request clarification or add additional context in comments.

Comments

3

The assignment operator in ruby is making a copy of the value only if it deal with POD (Plain Old Data) objects like numbers, strings. In other cases, it simply copies the reference to the object.

And don't forget, that dup (and clone) method makes only shallow copy of object. It means that if your array have other non-POD objects inside, they won't be copied.

inner = [1,2,3]
 => [1, 2, 3]
outer = [inner, 7,8,9]
 => [[1, 2, 3], 7, 8, 9]

outer_dup = outer.dup
inner.pop
 => 3

outer
 => [[1, 2], 7, 8, 9]
outer_dup
 => [[1, 2], 7, 8, 9]

You can avoid it by overriding clone method to handle making deep copy by yourself.

Comments

0

Ruby is very object oriented. With very few exceptions, Ruby almost always passes variables by reference, not value. It's a pretty important concept. Check this out. It isn't ruby, but it might help demystify it a bit. Hope that helps!

3 Comments

-1. This wrong. First off, Ruby is pass-by-value. Secondly, there are no exceptions, Ruby is always pass-by-value. If you want to know whether Ruby (or any other language) is pass-by-reference or pass-by-value, just try it out: def foo(bar) bar = 'reference' end; baz = 'value'; foo(baz); puts "Ruby is pass-by-#{baz}".
After reading other posts that you've made on this subject, it's clear that you're adhering to a strict Computer Science sense of the word. That just flat out doesn't make sense in this case. The OP is asking a question about passing an object around. Please consider being less pedantic.
I'm talking about Ruby, which doesn't even have primitives, only objects. I provided a simple test program in my comment which you can cut&paste into IRb yourself if you don't believe me.

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.