Deep copy?

A

Andrew Walrond

Is there a deep copy function that I've missed somehow? (dup and clone are
both shallow copy functions).

E.g. How can I make a deep copy of a Hash?

Ie if
a=['who'=>'me'],
I want
b = a.deepcopy
Such that
b['who'].replace('you')
doesn't result in
a == ['who'=>'you']

I could do
b=YAML::load(YAML::dump(a)
but it reeks of _wrongness_ ;)

Andrew Walrond
 
L

Lyndon Samson

Is there a deep copy function that I've missed somehow? (dup and clone are
both shallow copy functions).

E.g. How can I make a deep copy of a Hash?

Ie if
a=['who'=>'me'],
I want
b = a.deepcopy
Such that
b['who'].replace('you')
doesn't result in
a == ['who'=>'you']

I could do
b=YAML::load(YAML::dump(a)
but it reeks of _wrongness_ ;)

The idiom of choice seems to be to use Marshall instead.
 
J

Joel VanderWerf

Andrew said:
Is there a deep copy function that I've missed somehow? (dup and clone are
both shallow copy functions).

E.g. How can I make a deep copy of a Hash?

Ie if
a=['who'=>'me'],
I want
b = a.deepcopy
Such that
b['who'].replace('you')
doesn't result in
a == ['who'=>'you']

I could do
b=YAML::load(YAML::dump(a)
but it reeks of _wrongness_ ;)

Marshal is a little less wrong than YAML, and it is AFAIK the most
reliable and general deep copy in ruby.

There was at one time some talk of general-purpose object traversal:

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/64146
 
T

Trans

ruby-talk:64146 is from over 2 years ago. I wonder if any progress on
this idea has been made. Ruby 2.0?

T.
 
R

Robert Klemme

Trans said:
ruby-talk:64146 is from over 2 years ago. I wonder if any progress on
this idea has been made. Ruby 2.0?

Hm, why wait? You can cook one on your own:

Regards

robert


require 'set'

class Traversal
include Enumerable

def self.traverse(obj,&b)
v = self.new obj
v.each &b
v
end

def self.next_objects(obj)
case obj
when Hash
obj.keys + obj.values
when String
[]
when Enumerable
obj
else
obj.instance_variables.map{|v| obj.instance_variable_get v}
end
end

def initialize(obj)
@start = obj
end

def each
visited = Set.new
queue = [@start]

until queue.empty?
n = queue.shift
visited << n.object_id
tmp = yield n
# pp tmp
tmp.each {|ne| queue << ne unless visited.include? ne.object_id}
end

self
end
end

require 'pp'

h = {1=>"one", 2=>"two", 3=>"three"}
h[4] = h[2]
h[5] = h

pp h
puts "---------------"

Traversal.traverse h do |obj|
# pp obj.object_id, obj
pp obj
Traversal.next_objects obj
end
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,781
Messages
2,569,619
Members
45,314
Latest member
HugoKeogh

Latest Threads

Top