Turns out that simply adding the MooseX::Clone
role to the class provides a clone()
method that recursively clones attributes.
- For hashref/arrayref attributes, it copies structures.
- For scalars (including references) it simply does a shallow copy of the reference.
- If you add
traits => ['Clone']
to the attribute, it will recursively clone the attribute by calling clone()
on the attribute value.
To support cloning Set::Object
, I ended up creating a trait called CloneByCoercion
by subclassing the Clone
trait, parameterized with the type to coerce to/from before cloning.
So to use it, I wrote:
has 'blah' => (isa => 'Set::Object', is => rw,
traits => ['CloneByCoercion' => {to=>'ArrayRef'}]
);
MooseX::Types::Set::Object
provides coercions to and from ArrayRef (although I needed to patch a bug in it: the coercion to ArrayRef should return a reference, not a list)
I also modified MooseX::Clone
to keep an objects-seen hash, so that it supports cloning interlinked object structures with circular references.
I'll eventually get around to putting this stuff up on CPAN or submitting patches to the modules.