Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"

Re^3: Unable to make shallow copy of Moo hash ref attribute

by davido (Cardinal)
on Nov 13, 2018 at 16:10 UTC ( #1225727=note: print w/replies, xml ) Need Help??

in reply to Re^2: Unable to make shallow copy of Moo hash ref attribute
in thread Unable to make shallow copy of Moo hash ref attribute

Storable's dclone does what you are after, but may be heavier than you need, since it does a full freeze and thaw to and from memory. The advantage to dclone is it supports hooks to define serialization behavior. But often that's not needed. In cases where you don't need that flexibility, Clone provides a clone function that is somewhat lighter weight, and for a typical data structure will be faster.

In some cases rather than cloning a data structure you can get away with using local to override certain elements within the structure in a way where the changes unroll at end of dynamic scope. An example of this would be passing a structure in as an argument list, and needing to massage those args without having the changes propagate back to the caller. In that case, localizing a key or an element before fiddling with its value is a good approach that avoids a full clone.


Replies are listed 'Best First'.
Re^4: Unable to make shallow copy of Moo hash ref attribute
by davido (Cardinal) on Nov 14, 2018 at 16:10 UTC

    Sometimes a picture paints a thousand words, so here's a contrived example of what I'm getting at with respect to using local to allow changes to a data structure without letting those changes propagate outward (as a possible alternative to the thought "I need to clone this."):

    use Data::Dumper; $Data::Dumper::Sortkeys = 1; $Data::Dumper::Indent = 0; my $args = { foo => 1, baz => 2, }; print "Before calling mysub(\$args)\n"; print Dumper($args), "\n\n"; mysub($args); print "After calling mysub(\$args)\n"; print Dumper($args), "\n\n"; sub mysub { my $args = shift; local $args->{'foo'} = $args->{'foo'}; $args->{'foo'} += 100; # 101 now. print "Inside mysub()\n"; print Dumper($args), "\n\n"; othersub($args); } sub othersub { my $args = shift; local $args->{'baz'}; delete $args->{'baz'}; print "Inside othersub()\n"; print Dumper($args), "\n\n"; }

    This produces the following output:

    Before calling mysub($args) $VAR1 = {'baz' => 2,'foo' => 1}; Inside mysub() $VAR1 = {'baz' => 2,'foo' => 101}; Inside othersub() $VAR1 = {'foo' => 101}; After calling mysub($args) $VAR1 = {'baz' => 2,'foo' => 1};

    So with local we've been able to make changes to individual elements within the $args data structure without those changes propagating back out to the caller's data structure. In cases where the number of changes is small, you can use this sort of strategy rather than deep cloning the entire structure. However, there certainly are many legitimate uses for a deep clone, and the localization of structure elements is not the right tool for every situation. I just wanted to present it as one tool that may be useful in some cases.


      Thanks. local is one of those keywords that you'll often read about but rarely stop to think when it can be used when you are actually writing code.

      $PM = "Perl Monk's";
      $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest Vicar";
      $nysus = $PM . ' ' . $MCF;
      Click here if you love Perl Monks

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1225727]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (3)
As of 2019-05-20 00:23 GMT
Find Nodes?
    Voting Booth?
    Do you enjoy 3D movies?

    Results (123 votes). Check out past polls.