[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Deep copy?

Andrew Walrond

4/28/2005 6:19:00 PM

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


4 Answers

Lyndon Samson

4/28/2005 6:41:00 PM

0

On 4/29/05, Andrew Walrond <andrew@walrond.org> wrote:
> 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.


>
> Andrew Walrond
>
>


--
Into RFID? www.rfidnewsupdate.com Simple, fast, news.



Joel VanderWerf

4/28/2005 6:44:00 PM

0

Andrew Walrond wrote:
> 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-...


Trans

4/28/2005 7:23:00 PM

0

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

T.

Robert Klemme

4/29/2005 3:01:00 PM

0


"Trans" <transfire@gmail.com> schrieb im Newsbeitrag
news:1114716185.239134.214060@o13g2000cwo.googlegroups.com...
> 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