Dup and Clone

Could anyone kindly point out the difference between ‘dup’ and ‘clone’?

I’ve been having a look at the Ruby source code but I can’t find an official
explanation.

tia,

···


Justin Johnson

“Justin Johnson” justinj@mobiusent.com wrote in message
news:3d50209c$1_9@news5.nntpserver.com

Could anyone kindly point out the difference between ‘dup’ and ‘clone’?

I’ve been having a look at the Ruby source code but I can’t find an
official
explanation.

Hmmm, according to the Pickaxe book “In general, clone and dup may have
different semantics in descendent classes. While clone is used to duplicate
an object, including its internal state, dup typically uses the class of the
descendent object to create the new instance.”

I must say that this doesn’t make it clearer for myself either :confused:

Regards,
Paul

“Justin Johnson” justinj@mobiusent.com wrote in message
news:3d50209c$1_9@news5.nntpserver.com

Could anyone kindly point out the difference between ‘dup’ and ‘clone’?

As has been noted in other responses, they’re both kinds of “shallow”
copies. The primary difference is that ‘clone’ copies an object’s entire
state, including its freeze status and instance variables, whereas ‘dup’
only copies the basic object contents. Why this distinction? That is a dandy
question that I can’t answer. Nevertheless, here’s a quickie, meaningless
example of the dynamic duo:

s1 = "This is a string"
class << s1
  def foo=(f)
    @foo = f
  end
  def foo
    @foo
  end
end
s1.foo = 2
s1.freeze

s1_clone = s1.clone
s1_clone.frozen?    --> returns true
s1_clone.foo    --> returns 2

s1_dup   = s1.dup
s1_dup.frozen?    --> returns false
s1_dup.foo    --> error, basic String class doesn't have a "foo" method

Hope this helps,

Lyle

Paul E.C. Melis wrote:

Hmmm, according to the Pickaxe book “In general, clone and dup may have
different semantics in descendent classes. While clone is used to duplicate
an object, including its internal state, dup typically uses the class of the
descendent object to create the new instance.”

I must say that this doesn’t make it clearer for myself either :confused:

Agreed. There’s also the problem that ruby doesn’t seem to have a
deep-copy. If an object doesn’t provide its own deep-copy equivalent,
internal objects still reference the same object-id’s.
a = b.dup
A’s objects may have new clone’s of b’s values, but internal objects may
still point to the same object-id, so change’s to a may affect b.
I’d love to have some help on this one. It seems like an odd ommision -
or are classes supposed to impliment a copy-constructor like equivalent
? a = AClass.new( b) ?

Lyle Johnson wrote:

copies. The primary difference is that ‘clone’ copies an object’s entire
state, including its freeze status and instance variables, whereas ‘dup’
only copies the basic object contents. Why this distinction? That is a dandy

By golly, you’re right. A good thing to remember.

irb(main):001:0> x = “foo”
“foo”
irb(main):002:0> x.instance_eval { @y = 2 }
2
irb(main):003:0> x
“foo”
irb(main):004:0> x.instance_eval { @y }
2
irb(main):005:0> x.dup.instance_eval { @y }
nil
irb(main):006:0> x.clone.instance_eval { @y }
2

Can’t you deep copy using Marshal?

a = Marshal.restore(Marshal.dump(b))

Tom.

···

Paul E.C. Melis wrote:

Hmmm, according to the Pickaxe book “In general, clone and dup may have
different semantics in descendent classes. While clone is used to duplicate
an object, including its internal state, dup typically uses the class of
the
descendent object to create the new instance.”

I must say that this doesn’t make it clearer for myself either :confused:

Agreed. There’s also the problem that ruby doesn’t seem to have a
deep-copy. If an object doesn’t provide its own deep-copy equivalent,
internal objects still reference the same object-id’s.
a = b.dup
A’s objects may have new clone’s of b’s values, but internal objects may
still point to the same object-id, so change’s to a may affect b.
I’d love to have some help on this one. It seems like an odd ommision -
or are classes supposed to impliment a copy-constructor like equivalent
? a = AClass.new( b) ?


.^. .-------------------------------------------------------.
/V\ | Tom Gilbert, London, England | http://linuxbrit.co.uk |
/( )\ | Open Source/UNIX consultant | tom@linuxbrit.co.uk |
^^-^^ `-------------------------------------------------------’

Agreed. There's also the problem that ruby doesn't seem to have a
deep-copy.

This is not a problem, this is a feature. Try to think about RCO before
trying to introduce deep-copy.

Guy Decoux

Joel VanderWerf wrote:

Lyle Johnson wrote:

copies. The primary difference is that ‘clone’ copies an object’s entire
state, including its freeze status and instance variables, whereas ‘dup’
only copies the basic object contents.
[…]
irb(main):005:0> x.dup.instance_eval { @y }
nil
irb(main):006:0> x.clone.instance_eval { @y }
2

The freeze big I kinda understand, the instance variables, however, I
guess is a bug of some sort:

$ cat dup.rb
x = “foo”
x.instance_eval { @y = 2 }
puts "x.dup.y = " ,
x.dup.instance_eval { @y } #=> 2
puts "x.clone.y = " ,
x.clone.instance_eval { @y } #=> 2

$ ruby -v dup.rb ; /usr/local/bin/ruby -v dup.rb
ruby 1.6.6 (2001-12-26) [i586-linux-gnu]
dup.rb:7: warning: instance variable @y not initialized
x.dup.y =
nil
x.clone.y =
2
ruby 1.7.2 (2002-07-13) [i686-linux]
x.dup.y =
2
x.clone.y =
2

···


([ Kent Dahl ]/)_ ~ [ http://www.stud.ntnu.no/~kentda/ ]/~
))_student
/(( _d L b_/ NTNU - graduate engineering - 5. year )
( __õ|õ// ) )Industrial economics and technological management(
_
/ö____/ (_engineering.discipline=Computer::Technology)

Tom Gilbert wrote:

Can’t you deep copy using Marshal?

a = Marshal.restore(Marshal.dump(b))

I guess(?) It seems like a pretty major hack though. It really should
be built into the language, or into the standard
library distribution.

a) It’s ugly.
b) Not everything can be marhalled anyway.

IMHO, the right thing to do is to redefine clone for those classes that
need special treatment. The object should know how to clone it self.

Of course, something like the following would be nice the base distro.
Notice how it just redefines clone, and also uses clone to copy it’s
instance variable as well – so to be a true deep copy the instance
variables have to include the DeepClone as well.

Untested – written from memory:

module DeepClone
alias clone shallow_clone
def clone
klone = self.shallow_clone
self.instance_variables.each { |var|
val = self.var.clone
klone.send(“#{var}=”,val)
}
return klone
end
end

– Nikodemus

···

On Wed, 7 Aug 2002, Tom Gilbert wrote:

a = Marshal.restore(Marshal.dump(b))


I refuse to have a battle of wits with an unarmed person.

Kent Dahl wrote:

The freeze big I kinda understand, the instance variables, however, I
guess is a bug of some sort:

$ cat dup.rb
x = “foo”
x.instance_eval { @y = 2 }
puts "x.dup.y = " ,
x.dup.instance_eval { @y } #=> 2
puts "x.clone.y = " ,
x.clone.instance_eval { @y } #=> 2

$ ruby -v dup.rb ; /usr/local/bin/ruby -v dup.rb
ruby 1.6.6 (2001-12-26) [i586-linux-gnu]
dup.rb:7: warning: instance variable @y not initialized
x.dup.y =
nil
x.clone.y =
2
ruby 1.7.2 (2002-07-13) [i686-linux]
x.dup.y =
2
x.clone.y =
2

Hmmm… I see the same changed in behavior here when going from Ruby
1.6.7 to Ruby 1.7.2. And I don’t see it mentioned in the doc/NEWS so I
wonder if this was an intentional change?

Patrick Bennett wrote:

Tom Gilbert wrote:

Can’t you deep copy using Marshal?

a = Marshal.restore(Marshal.dump(b))

I guess(?) It seems like a pretty major hack though. It really should
be built into the language, or into the standard
library distribution.

I agree it seems hackish to generate strings just to deep-copy objects,
but there is an advantage to using Marshal: it guarantees that this deep
copy operation has exactly the same semantics as sending objects to
disk or to other processes. What if some class defined its own _dump and
_load (maybe because the objects have a reference to some large shared
data structure), but forgot to do whatever it has to do so that deep
copy follows the same principle?

Hmmm... I see the same changed in behavior here when going from Ruby
1.6.7 to Ruby 1.7.2. And I don't see it mentioned in the doc/NEWS so I
wonder if this was an intentional change?

The change is intentional.

Guy Decoux

Hi –

···

On Wed, 7 Aug 2002, Lyle Johnson wrote:

Hmmm… I see the same changed in behavior here when going from Ruby
1.6.7 to Ruby 1.7.2. And I don’t see it mentioned in the doc/NEWS so I
wonder if this was an intentional change?

Yes – from ChangeLog:

Tue Dec 4 17:43:10 2001 Yukihiro Matsumoto matz@ruby-lang.org

* string.c (rb_str_dup): uses DUPSETUP.  now properly copies
  instance variables too.

David


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

Joel VanderWerf wrote:

Patrick Bennett wrote:

Tom Gilbert wrote:

Can’t you deep copy using Marshal?

a = Marshal.restore(Marshal.dump(b))

I guess(?) It seems like a pretty major hack though. It really
should be built into the language, or into the standard
library distribution.

I agree it seems hackish to generate strings just to deep-copy
objects, but there is an advantage to using Marshal: it guarantees
that this deep copy operation has exactly the same semantics as
sending objects to disk or to other processes.

Good point. I guess I would (well, me at leats) probably just add a
deepCopy method to Object that used marshall to accomplish it.
class Object
def deepCopy
return Marshal.restore(Marshal.dump(self))
end
end

a = “Tim”
b = a.deepCopy
b[0] = ‘J’
p a, b

Strings are admittedly a bad example (because dup or clone for a string
works just fine), but it’s an obvious litmus test.

The thing is, if it’s so easy to do, and it seems to ‘work,’ why isn’t
it already defined in Ruby?
Any experts out there care to shed some light on the subject to a Ruby
newbie?

What if some class defined its own _dump and _load (maybe because the
objects have a reference to some large shared data structure), but
forgot to do whatever it has to do so that deep copy follows the same
principle?

Honestly, I think it would be far more likely for the ‘average’ class to

···

not< have custom _dump/_load methods

I can’t think of a good reason that there isn’t a deep copy supplied. The
marshal solution works but is a bit of a sledgehammer approach.

If an object is capable of cloning itself then you’d think a deep copy would
be easy. Except… how would you efficiently avoid cycles? Marshal does it
by remembering what it’s marshalled - like any persistency system.

To do this you’d can use hash table (addr_hash) that held <object,

The basic algorithm is something like:

deep_copy( object )
if object is not in addr_hash
newaddress = clone object
add_hash <object, newaddress>
for each child object
child = deep_copy( child )
end
end
return newaddress
end

Perhaps now I can see why this was avoided…

···


Justin Johnson

“Patrick Bennett” patrick.bennett@inin.com wrote in message
news:3D50845B.9040305@inin.com

Joel VanderWerf wrote:

Patrick Bennett wrote:

Tom Gilbert wrote:

Can’t you deep copy using Marshal?

a = Marshal.restore(Marshal.dump(b))

I guess(?) It seems like a pretty major hack though. It really
should be built into the language, or into the standard
library distribution.

I agree it seems hackish to generate strings just to deep-copy
objects, but there is an advantage to using Marshal: it guarantees
that this deep copy operation has exactly the same semantics as
sending objects to disk or to other processes.

Good point. I guess I would (well, me at leats) probably just add a
deepCopy method to Object that used marshall to accomplish it.
class Object
def deepCopy
return Marshal.restore(Marshal.dump(self))
end
end

a = “Tim”
b = a.deepCopy
b[0] = ‘J’
p a, b

Strings are admittedly a bad example (because dup or clone for a string
works just fine), but it’s an obvious litmus test.

The thing is, if it’s so easy to do, and it seems to ‘work,’ why isn’t
it already defined in Ruby?
Any experts out there care to shed some light on the subject to a Ruby
newbie?

What if some class defined its own _dump and _load (maybe because the
objects have a reference to some large shared data structure), but
forgot to do whatever it has to do so that deep copy follows the same
principle?

Honestly, I think it would be far more likely for the ‘average’ class to

not< have custom _dump/_load methods

I think that’s because there are cases when Marshal won’t work. Adding a
core feature that “sometimes works” is not something I’d do :slight_smile:

Quoted from ri Marshal:

Some objects cannot be dumped: if the objects to be dumped include
bindings, procedure objects, instances of class IO, or singleton
objects, a TypeError will be raised.

Tom.

···

Strings are admittedly a bad example (because dup or clone for a string
works just fine), but it’s an obvious litmus test.

The thing is, if it’s so easy to do, and it seems to ‘work,’ why isn’t
it already defined in Ruby?
Any experts out there care to shed some light on the subject to a Ruby
newbie?


.^. .-------------------------------------------------------.
/V\ | Tom Gilbert, London, England | http://linuxbrit.co.uk |
/( )\ | Open Source/UNIX consultant | tom@linuxbrit.co.uk |
^^-^^ `-------------------------------------------------------’