How to make a separate copy of an object in Perl 6? - clone

I don't fully understand the docs, so I've tried clone, and it seems if there is an attribute of a mutable class, it can be changed in the new object using the old one (and that's what I don't want). How to make them (i.e. the copy and the original) fully separate?
class A {
has #.a;
}
my A $x = A.new;
my A $y = A.new;
$x.a = 1, 2;
$y = $x.clone;
$x.a.push(4);
say $y.a; # [1 2 4]

The default clone inherited from Mu is shallow, as documented. This means that it will only copy the object itself, but not anything the object references. It is possible to override clone to have your preferred semantics, which is probably the best thing to do here.
One useful thing to know in doing this is that clone takes named parameters and uses them to assign to properties of the cloned object. This is worth knowing because:
One should make sure to handle this when overriding clone, to avoid surprises to users of the overridden clone method who use this feature
One can use this when overriding clone to succinctly opt in to cloning of a particular array or hash attribute
Thus for the case in the question, writing:
class A {
has #.a;
method clone() {
callwith(:#!a, |%_)
}
}
Will result in the output [1 2] as presumably desired. How does it work?
The |%_ just passes on any tweaks the caller of this clone method specified
:#!a is short for a => #!a
callwith calls the inherited clone (from Mu in this case)
Assignment, not binding, semantics are used on #!a in the target object (just as during object construction), resulting in a copy of the array
This shortcut works for hash attributes too. For an attribute containing another object, it'd look like callsame(x => $!x.clone).

Related

ruby: check if two variables are the same instance

I have a class Issue in which each class has a key field. Because keys are meant to be unique, I overrode the comparison operator such that two Issue objects are compared based on key like so:
def ==(other_issue)
other_issue.key == #key
end
However, I am dealing with a case in which two there may be two variables referring to the same instance of an Issue, and thus a comparison by key would not distinguish between them. Is there any way I could check if the two variables refer to the same place?
According to the source, the Object#equal? method should do what you're trying to do:
// From object.c
rb_obj_equal(VALUE obj1, VALUE obj2)
{
if (obj1 == obj2) return Qtrue;
return Qfalse;
}
So the ruby code you would write is:
obj1.equal?(obj2)
No, not really. And that is Good Thing™.
A basic tenet of object-orientation is that one object can simulate another object. If you could tell whether or not two objects are the same object ("Reference Equality"), then you could tell apart the simulation from the real thing, thus breaking object-orientation … which, for an object-oriented language like Ruby is not so good.
The default implementation of Object#equal? does indeed check for reference equality, but, just like every other method in Ruby, it can be overridden in subclasses or monkey-patched, so there is no way to guarantee that it will actually check for reference equality. And that is how it should be.

Deleting an instance of a class via a method of that class

I have a class for pieces on a board. I want to be able to delete an instance of Piece so that anything else in the program that points to that piece will just point to nil.
Here's the very basic code version of what I want to do:
piece = Piece.new
variable = piece
variable #=> <Piece:0x0000000xxxxxxxx>
piece.delete
variable #=> nil
This seems like a very basic task so I feel like I'm missing something obvious. I've tried creating a delete method for the class with "self = nil", but this returns an error ("Can't change the value of self").
So far I have just worked around this by updating the other things that point to the object in my 'delete' method, but it seems like there should be a better way.
This is not possible.
Firstly, Ruby is an object-oriented language, which means that all manipulation is done via messages to objects, and all that is manipulated are objects. Variables are not objects, therefore you cannot manipulate them. (The only things you can do with variables are assign a value to them and dereference them.)
And even if you could manipulate variables, you would still need to hunt down every single reference to the object in question and remove it, in order for the object to be eligible for "deletion" (i.e. garbage collection).

What is the correct way to implement a "clone" method in languages that do not support type reflection and have no built-in cloning mechanism?

Problem background
Suppose I have a class called Transaction and a subclass called NetTransaction. The Transaction class implements a clone method which constructs a new Transaction with multiple constructor parameters.
Such a cloning pattern presents a problem for subclasses like NetTransaction, because calling super.clone will return an object of type Transaction which cannot be up casted to NetTransaction. Therefore, I'd have to reimplement (duplicate) the code in the Transaction class's clone method. Obviously, this is an unacceptable pattern.
Java's solution -- works for languages with built-in cloning logic or type reflection
In Java (so I've read), calling super.clone always returns an object of the correct type as long as every override in the chain calls super.clone, because the base Object's clone method will automatically return an object of the correct type, presumably a feature built into the runtime.
The existence of such a clone method implies that every clonable object must have a parameterless default constructor (either explicitly or implicitly) for two reasons. Firstly, Object's implementation would not be capable of choosing an arbitrary constructor for a subclass it knows nothing about, hence the need for a parameterless constructor. Secondly, although a copy constructor might be the next logical choice, it implies that every object in the class chain would also have to have a copy constructor, otherwise every copy constructor would be faced with the same decision as clone (i.e. to call the default constructor or a copy constructor). That ultimately implies that all the cloning logic would have to be in copy constructors, which would make overriding "clone" unnecessary; therefore, we arrive at the logical conclusion that it would be self-defeating to have clone call anything other than a parameterless default constructor (i.e. the runtime would have to create an instance that require no special construction logic to run).
So Java's cloning implementation, which also seems to provide some built-in shallow copying, is one way to implement cloning that makes sense.
Correct alternative for languages without built-in cloning or type reflection?
But what about other languages that don't have such built-in functionality and lack type reflection? How should they implement cloning? Are copy constructors the only way to go?
I think the only way that really makes sense is copy constructors, and as far as implementing or overriding a clone method for the sake of returning a common interface or base type or just "object", the correct implementation is to simply always call the current object's copy constructor. Is this correct?
The pattern would be, in C# for example:
class A
{
public A( A original_to_copy ) { /*copy fields specific to A*/ }
public object clone() { return new A( this ); }
}
class B: A
{
public B( B original_to_copy ):this (original_to_copy) { /*copy fields specific to B*/ }
public override object clone() { return new B( this ); }
}
class C: B
{
public C( C original_to_copy ):this(original_to_copy) { /*copy fields specific to C*/ }
public override object clone() { return new C( this ); }
}
In systems without a built-in cloning facility, there's really no alternative to using a virtual clone method chain to a copy constructor. I would suggest, however, that one should have the copy constructor and virtual cloning method be protected, and have the base-class copy constructor throw an exception if the exact types of the passed-in object does not match the exact type of the object under construction. Public cloning methods should not be virtual, but should instead chain to the virtual method and cast the result to their own type.
When practical, one should avoid having classes which expose public cloning methods be inheritable; consumers should instead refer to class instances using interface types. If some of the consumers of a type will need to clone it and others won't, some potential derivatives of the type could not logically be cloned, and if a derivative of the type which wasn't cloneable should be usable by code that doesn't need to clone it, splitting things that way will allow for the existence of BaseFoo, CloneableBaseFoo, FancyFoo, and CloneableFancyFoo types; code which needs fancy abilities but doesn't need to clone an object will be able to accept FancyFoo and CloneableFancyFoo objects, while code that doesn't need a fancy object but needs cloning ability will be able to accept CloneableBaseFoo and CloneableFancyFoo objects.

Why does String::sub!() change the original of a cloned object in Ruby?

I have a struct in my Ruby code that looks somewhat like this
Parameter = Struct.new(:name, :id, :default_value, :minimum, :maximum)
later, I create an instance of this struct using
freq = Parameter.new('frequency', 15, 1000.0, 20.0, 20000.0)
At some point, I need an exact duplicate of this struct, so I call
newFreq = freq.clone
Then, I change newFreq's name
newFreq.name.sub!('f', 'newF')
Which, miraculously, changes freq.name, too!
A simple assignment like newFreq.name = 'newFrequency' does not change freq.
Is this the way this is supposed to work?
Edit: Is it a good idea to use a class instead of a struct and overload clone to make a deep copy?
newFreq is a shallow copy of freq. That means that each of the references stored inside of newFreq points to the object as the ones stored in freq. You can change where the references point independantly (newFreq.name = newFreq.name.sub 'f','newF'), but if you call a method that mutates the object, both newFreq and freq will be affected.
See also http://en.wikipedia.org/wiki/Object_copy
The Object#clone method performs shallow copy. You need deep copy to get the job done.
Follow this link to learn about deep copy in Ruby.

What does it mean to clone() an object?

What is object cloning in vb6 or java? In what situation do we use a clone? What does cloning objects mean? Can any one tell me with example please.
Cloning is actually copying the object data into a new object.
This example doesn't clone the data:
Foo p = new Foo();
Foo o = p;
If Foo has a member a and you change p.a then o.a also changes because both p and o point to the same object.
However,
Foo p = new Foo();
Foo o = p.Clone();
In this case if you change p.a then o.a remains the same because they actually point to separate objects.
There are actually two different ways you can clone: shallow clone or deep clone.
A shallow clone just makes a new object and copies the members into the new object. This means that if one of the members is actually a pointer to another object then that object will be shared between the old object and new object.
A deep clone actually goes through and clones all the members into the new object. That way the objects are complete copies of all the data.
Generaly speaking objects are passed by reference. So if you say $objB=$objA you are not getting a new object; you are getting a new name for the same object. However, if you say $objB= clone $objA you get a copy of $objA. In the first case, whatever you do to $objB also happens to $objA. In the 2nd case, $objB is independent.

Resources