2

I'm new to ruby and was wondering how I'd go about this

For example:

a = [1,2,3,4]
b = []

b.push(a)
a.pop
a.pop

print b
# => [[1,2]]

I was expecting b to remain [[1,2,3,4]]

a seems to be pushed into b by reference, rather than value. I'd like b to stay as it is regardless of what I do to a in the future; how do I go about doing this in Ruby?

zoopz
  • 1,099
  • 2
  • 9
  • 10
  • 1
    `b` remains the same after `a = [1, 2]`. The assignment doesn't affect the array in `b` at all. – Stefan Feb 05 '16 at 11:15
  • oh, so it does. however, if i do a.pop instead of a = [1,2], i found the value of b changed. i've modified the original question – zoopz Feb 05 '16 at 11:30
  • 2
    No, the value of `b` *doesn't* change. It still points to the same object as before (which is, incidentally, the same object that `a` also points to). *What* changes is the internal state of the object, but that is something completely different. – Jörg W Mittag Feb 05 '16 at 11:35
  • You pass copy of the object, using `dup`, for example `b.push(a.dup)`. But be aware that it's only a shallow copy and if `a` holds a reference for other object, this object won't be copied. – Marek Lipka Feb 05 '16 at 11:35
  • "By reference" and "by value" are not really very helpful terms in Ruby. Strictly speaking, *all* parameters are passed by value. But sometimes the thing that is passed by value is a reference, so if you change it, you are effectively changing the value of the thing that is passed... – Andy Jones Feb 05 '16 at 13:05

2 Answers2

3

a is an array reference, so to push its value into b, you'll need to copy it:

b.push(a.dup)

This is similar to using strdup in C, where strings are pointers.

banana
  • 603
  • 5
  • 10
  • 1
    I don't think "value" is the correct term. `a.dup` merely creates a copy, i.e. a new array containing the same elements. – Stefan Feb 05 '16 at 12:29
1

You could use splat operator and push elements of a into b instead of whole array a.

b.push(*a)
#=> [1, 2, 3, 4]

If you wanted to push an array, then, use

b.push([*a])
#=> [[1, 2, 3, 4]]
Wand Maker
  • 18,476
  • 8
  • 53
  • 87