nysus has asked for the wisdom of the Perl Monks concerning the following question:

This is driving me nuts:

has 'tree' => ( is => 'ro', isa => sub { {} }, default => sub { { '/' => { children => {} } } } + ); has 'clean_tree' => ( is => 'rw', lazy => 1, predicate => 1, ); sub BUILD { my $s = shift; $s->app->add_hook (Dancer2::Core::Hook->new ( name => 'before_template', code => sub { ... if (!$s->has_clean_tree) { my %tree = %{$s->tree}; # Attempting to make shallow copy he +re. $s->clean_tree(\%tree); } # set active my $tree = $s->clean_tree->{'/'}; foreach my $segment (@segments) { $tree->{children}{$segment}{active} = 1; $tree = $tree->{children}{$segment}; } ... } )); }

$s->clean_tree is reflecting $s->tree despite trying to make a shallow copy of $s->tree first..

$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

Replies are listed 'Best First'.
Re: Unable to make shallow copy of Moo hash ref attribute
by haukex (Archbishop) on Nov 13, 2018 at 08:28 UTC

    It sounds to me like you want a deep copy rather than a shallow one? That's what Storable's dclone does.

    use warnings; use strict; use Data::Dump 'dd'; use Storable 'dclone'; my $hr = { foo => { bar => "quz" } }; my $deep = dclone($hr); $deep->{foo}{bar} = 'baz'; $deep->{x} = 'y'; dd $deep; # { foo => { bar => "baz" }, x => "y" } dd $hr; # { foo => { bar => "quz" } } unchanged my $shallow = { %{ $hr } }; $shallow->{foo}{bar} = 'baz'; $shallow->{x} = 'y'; dd $shallow; # { foo => { bar => "baz" }, x => "y" } dd $hr; # { foo => { bar => "baz" } } # original changed ^^^

      Right. I was confused on the terminology. Had it backwards. Was part of the reason for my frustration.

      $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

        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.


        Dave

Re: Unable to make shallow copy of Moo hash ref attribute
by nysus (Parson) on Nov 13, 2018 at 06:32 UTC
    OK, had to use Storable's dclone function.

    $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