Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deep cloning Moose object with attributes that are ArrayRef[Object] and Set::Object

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!

like image 318
PBJ Avatar asked Aug 21 '10 07:08

PBJ


People also ask

How to clone deep object in javascript?

Copy an Object With Object. assign() was the most popular way to deep copy an object. Object. assign() will copy everything into the new object, including any functions. Mutating the copied object also doesn't affect the original object.

How do you clone an object?

To clone an object, use the Object class's clone() method. It is the quickest way to duplicate an array. The class whose object clone we wish to generate must implement the Cloneable interface. If the Cloneable interface is not implemented, the clone() function throws a CloneNotSupportedException .

What is clone deep javascript?

cloneDeep() method is used to create a deep copy of the value i.e. it recursively clones the value. This method is similar to the _.

What is object cloning in javascript?

Cloning. Cloning in javascript is nothing but copying an object properties to another object so as to avoid creation of an object that already exists. There are a few ways to clone a javascript object. 1) Iterating through each property and copy them to a new object. 2) Using JSON method.


2 Answers

I haven't used any of the pieces here (MooseX::Clone, MooseX::Compile, and Set::Object), so here's just a rough outline of where I'd start, from my review of the docs and general knowledge of Moose architecture:

  • MooseX::Clone gives your object a clone() method, which will then call clone() on each of your attributes with the 'Clone' trait.
  • so, you need to add a clone() method to both of your attributes...
  • it would be my ambitious hope that MooseX::Clone can handle native attribute arrayrefs, but since it probably doesn't, you may get to extend that feature yourself (i.e. if 'action_sequence' has the option traits => ['Array'], it is smart enough that the clone method is actually defined via handles => { clone => [ 'map', 'clone' ] } -- i.e. clone the attribute by calling clone() on each of the member elements) -- here is likely where you would be submitting your first patch
  • Set::Object's documentation suggests that you can clone objects reliably with Storable::dclone (which you should verify, and flog the author and/or supply patches if this is not correct)
  • and now you need to add a clone() method to the Set::Object attribute, which the docs suggest you do with MooseX::Compile (and here is where you should come on irc.perl.org #moose and give us a blow-by-blow of your progress, so we can make a documentary about it later) :)
like image 152
Ether Avatar answered Oct 08 '22 10:10

Ether


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.

like image 28
PBJ Avatar answered Oct 08 '22 12:10

PBJ