O
OliverMarchand
Dear Ruby people,
I spent quite a while yesterday reviewing the discussions on deep
copying in ruby. An approach that I have not seen anywhere is to use a
combination of eval and inspect to deep copy an object. The essence of
the idea is:
obj_copy = eval(obj.inspect)
The standard approach is via Marshalling, but it doesn't really work:
e.g.
[[1,2,3]]*3
is a typical array, which does not contain three independent arrays,
but three pointers to the same array [1,2,3]. When Marshalling is
applied to copy this object the internal structure is preserved, which
may be a desirable feature or not. BTW: is there a good way to display
(a) that exact internal structure, (b) the contents of a Marshal
serialize string?
Now with the above eval method you get a real deep copy of the
123array, but the method is (a) slow and (b) does not work for objects
which do not return a string that can be used for instantiation of that
exact same object upon receiving inspect (which is the regular case).
But it works for simple combinations of strings, hashes, arrasy, floats
and ints, etc.
Now to make it more usable, I have combined the two in a very simple
module. One could also mix these into classes to make them accessible
via a method. The code below works for more things than the simple
Marshal version, but the behaviour is far from "under perfect control",
thus I hesitate to continue with this module. Are there comments and/or
better version and/or extensions out there?
---
module Deepcopy
def Deepcopy.bymarshal(obj)
return Marshal.load(Marshal.dump(obj))
end
def Deepcopy.byeval(obj)
if obj==nil
return nil
else
begin
e = eval(obj.inspect)
rescue Exception
end
e = Deepcopy.bymarshal(obj) if e == nil
return e
end
end
end
---
ciao,
Oliver
--
Oliver Marchand
Wunderlistr. 45
CH-8037 Zürich
Mobile: +41 78 8032102
Email (private): (e-mail address removed)
Email (work): (e-mail address removed)
I spent quite a while yesterday reviewing the discussions on deep
copying in ruby. An approach that I have not seen anywhere is to use a
combination of eval and inspect to deep copy an object. The essence of
the idea is:
obj_copy = eval(obj.inspect)
The standard approach is via Marshalling, but it doesn't really work:
e.g.
[[1,2,3]]*3
is a typical array, which does not contain three independent arrays,
but three pointers to the same array [1,2,3]. When Marshalling is
applied to copy this object the internal structure is preserved, which
may be a desirable feature or not. BTW: is there a good way to display
(a) that exact internal structure, (b) the contents of a Marshal
serialize string?
Now with the above eval method you get a real deep copy of the
123array, but the method is (a) slow and (b) does not work for objects
which do not return a string that can be used for instantiation of that
exact same object upon receiving inspect (which is the regular case).
But it works for simple combinations of strings, hashes, arrasy, floats
and ints, etc.
Now to make it more usable, I have combined the two in a very simple
module. One could also mix these into classes to make them accessible
via a method. The code below works for more things than the simple
Marshal version, but the behaviour is far from "under perfect control",
thus I hesitate to continue with this module. Are there comments and/or
better version and/or extensions out there?
---
module Deepcopy
def Deepcopy.bymarshal(obj)
return Marshal.load(Marshal.dump(obj))
end
def Deepcopy.byeval(obj)
if obj==nil
return nil
else
begin
e = eval(obj.inspect)
rescue Exception
end
e = Deepcopy.bymarshal(obj) if e == nil
return e
end
end
end
---
ciao,
Oliver
--
Oliver Marchand
Wunderlistr. 45
CH-8037 Zürich
Mobile: +41 78 8032102
Email (private): (e-mail address removed)
Email (work): (e-mail address removed)