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:
clone, to avoid surprises to users of the overridden clone method who use this featureclone to succinctly opt in to cloning of a particular array or hash attributeThus 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?
clone method specified:@!a is short for a => @!a
callwith calls the inherited clone (from Mu in this case)@!a in the target object (just as during object construction), resulting in a copy of the arrayThis shortcut works for hash attributes too. For an attribute containing another object, it'd look like callsame(x => $!x.clone).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With