Deep copy?

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_ :wink:

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_ :wink:

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

···

On 4/29/05, Andrew Walrond <andrew@walrond.org> wrote:

Andrew Walrond

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

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_ :wink:

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

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

T.

"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