I've got a Moose object:
class My::Game {
has 'players' => (isa => 'Set::Object', ...)
has 'action_sequence' => (isa => 'ArrayRef[My::Game::Action]', ...)
}
Now I want to be able to clone this object with a call like $game2 = $game->clone;
How do I deep clone it so that the objects in the ArrayRef are cloned? And more trickily, the Set::Object?
I've looked at MooseX::Clone, but I'm unclear how to apply it to this case. Example code would be appreciated.
Thanks!
Turns out that simply adding the MooseX::Clone
role to the class provides a clone()
method that recursively clones attributes.
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.