Alan Slater wrote:
arrays (even arrays of ‘primitives’ like strings) don’t actually
contain the objects that fill each entry, they instead (effectively)
link to those objects.
Yes - they contain references to objects.
So, .delete_at and .slice! (for example) don’t
remove things from the array, they delete the objects that are being
linked to completely.
No - they delete the references from the array.
The objects themselves are unchanged. If there are other references to
them elsewhere in the system, they will live on. If the array element
was the only reference to the object, so that there are no more now,
then at some point in the future the object will be garbage-collected.
This explains my problem (why, whenever I delete an entry from an array,
it also deletes it from every copy of the array).
No - you are deleting from a single array, but you have multiple
references to that array from other places, so they all see the same
changed array.
A good way to probe this is with the ‘object_id’ method.
irb(main):001:0> a = [[1,2,3],[4,5,6]]
=> [[1, 2, 3], [4, 5, 6]]
irb(main):002:0> a.object_id
=> -605380508
irb(main):003:0> a[0].object_id
=> -605380598
irb(main):004:0> a[1].object_id
=> -605380608
irb(main):005:0> b = a.dup
=> [[1, 2, 3], [4, 5, 6]]
irb(main):006:0> b.object_id
=> -605417698
irb(main):007:0> b[0].object_id
=> -605380598
irb(main):008:0> b[1].object_id
=> -605380608
You can see that a and b are different objects, but a[0] and b[0] point
to the same object (ditto a[1] and b[1]). Diagramatically:
a -----> [ . , . ]
| |
v v
[1,2,3] [4,5,6]
^ ^
| |
b -----> [ . , . ]
The sub-arrays don’t belong to ‘a’ any more than they belong to ‘b’. So
the consequence is:
irb(main):009:0> a[0] << 99
=> [1, 2, 3, 99]
irb(main):010:0> a
=> [[1, 2, 3, 99], [4, 5, 6]]
irb(main):011:0> b
=> [[1, 2, 3, 99], [4, 5, 6]]
However if you make a modification to one of the outer arrays, e.g. by
adding or removing an element, this is fine:
irb(main):012:0> a << [7,8,9]
=> [[1, 2, 3, 99], [4, 5, 6], [7, 8, 9]]
irb(main):013:0> a
=> [[1, 2, 3, 99], [4, 5, 6], [7, 8, 9]]
irb(main):014:0> b
=> [[1, 2, 3, 99], [4, 5, 6]]
So, how could I simply remove an object from an array, without deleting
the object itself?
slice! or delete_at
Regards,
Brian.