From: Robert Klemme Date: 2008-03-22T22:34:53+09:00 Subject: Re: Cloning arrays On 22.03.2008 14:10, Len Lawrence wrote: > Another newbie question. I have started recoding some of my homegrown > Tcl/Tk applications in Ruby/rubytk and have hit an unexpected snag when > attempting to clone arrays. The following code is snipped verbatim from > the program: > > # Calculate coordinates for the Postscript page canvas and the > # label icons canvas in the setupInkjet window. > > def User.calcxy ( disposition, f ) > > xygrid = { } > > # Split the disposition string into x and y counts. > xy = Typefaces::Disposition[disposition] > # Obtain the label dimensions. > labelsize = Typefaces::Labelsizes[disposition] > # Populate the coordinate data structure. > xygrid['x'] = nx = xy[0] > xygrid['y'] = ny = xy[1] > xygrid['dx'] = dx = labelsize[0] * f > xygrid['dy'] = dy = labelsize[1] * f > # Obtain an array of 4 element arrays from the Typefaces module. > # These represent opposing corners of the address spaces on the > # Postscript canvas. > xygrid['page'] = Typefaces.labelgrid( disposition ) > puts 'page coordinates' > puts xygrid['page'][0] > puts '______________' > # Copy the page label coordinates. > e = xygrid['page'].clone > # Shrink the label icon coordinates. > e.each { |z| z.collect! { |d| d *= f } } > # Shrink the icons further to make separations visible. > e.each { |z| z[2] -= 2.0; z[3] -= 2.0 } > # Save the label icon coordinates. > xygrid['boxes'] = e > puts 'page again' > puts xygrid['page'][0] > puts 'boxes' > puts e[0] > puts '==============' > xygrid['max'] = nx * ny > return xygrid > > end > > The diagnostics at 'page again' and 'boxes' show that the copy of the > original array has been successfully processed but the original array now > reflects the same values. The 'page' and 'boxes' arrays are to be used in > different circumstances. > > What am I missing? It is bound to be something simple or something > fundamental. I tried Object#dup also - same result: Your issue is caused by the fact that dup and clone to shallow copies only, i.e. both copies of a clone Array contain the exact same instances. Now you modify those instances and of course changes are seen via both arrays: # Shrink the label icon coordinates. e.each { |z| z.collect! { |d| d *= f } } # Shrink the icons further to make separations visible. e.each { |z| z[2] -= 2.0; z[3] -= 2.0 } A solution would be to do e = xygrid['page'].map do |z| z = z.map { |d| d *= f } z[2] -= 2.0; z[3] -= 2.0 z end Or you can do a deep copy via the usual Marshal idiom e = Marshal.load(Marshal.dump(xygrid['page'])) Kind regards robert