Good morning, William.
I’ve tried all the other possibilities of independent copies of one array in another without using the assignment = :
push, concat.
Only the method << works properly. I do not know if that is normal. On the other hand I do not understand why the creation of a new initialized table like:
Array.new (OldArray)
does not change pointer?
Yours
You get a new outer-most Array, but the elements of the new Array still “point” to the original objects. This is called a “shallow copy” and why you need to manually copy each element as well.
EDIT: The Ruby docs are outdated and the Array constructor no longer uses #to_ary instead calls rb_ary_replace directly. So Array::new(other_array)will create a shallow copy.
To really produce a shallow copy you can do …
pts = Array.new(pointsArray.dup)
However the Array constructor call to Array::new is totally unnecessary as Object#dup has already produced a shallow copy.
Deep copy of an Array
The Array#map enumerator creates a new array (mapping the members of the new array to the result of executing an iterator block for each member of the old array.)
Using it you can iterate and duplicate the inner (nested) arrays …
I was just pointing out what the docs say it does. (Verified that Ruby docs are incorrect.)
Actually clicking on the toggle C source does not work for the :new method.
(I’d have to go look up the source at GitHub to see if the doc is incorrect.)
I also see that their #object_id is unique.
I would not be surprised if the ::new documentation was outdated, and reflects the situation before some later change to #to_ary.
::new does not call #to_ary in order to make the copy … it now calls rb_ary_replace directly.
(This is from rb_ary_initialize which begins at L726.
The #to_ary method just returns itself if the receiver is of class Array.
If the receiver is a subclass of Array it then returns a copy by creating a new array and then calling rb_ary_replace to stuff the new array with contents of the old subclass object …
module Kernel
# Anything that can be marshaled can be copied in totality.
#
# "ABC".deep_copy #=> "ABC"
#
# NOTE: Not sure why we wouldn't just call this #copy, but
# the term +deep_copy+ seems to be the common practive.
def deep_copy
Marshal::load(Marshal::dump(self))
end
end
pts = []
pts= pointsArray.deep_copy
Please beware that extensions modifying code Ruby API will be rejected from the Extension Warehouse.
(I would recommend not posting examples that demonstrate modifying the Ruby API as we often see this eventually make their way into extensions - which in turn we reject causing more work for developers.)
Marshal does not know what to do with API class objects, so if an array contains things other than simple core class objects, this would not be a good way to go.