title: Deep cloning of inside-out Perl classes - how to use methods from copied objects?
body: <p>I have 3 classes declared as inside-out Perl classes using <code>Class::Std</code>. In one of these 3, there's a hash reference stored in <code>$basket{ident $self}</code> that looks like so (output of Data::Dumper):</p>
  
  <pre><code>$VAR1 = {
            'auto' =&gt; {
                        'items' =&gt; {
                                     'abc' =&gt; bless( do{\(my $o = undef)}, 'Item' )
                                   },
                        'obj' =&gt; bless( do{\(my $o = undef)}, 'Category' )
                      }
          };
  </code></pre>
  
  <p>I need to take this hash reference and create everything in it again (deep cloning). I tried to use <code>dclone</code> from <code>Storable</code> like so:</p>
  
  <pre><code>my $new_basket = dclone $basket{ident $self};
  </code></pre>
  
  <p>When I print the hashes, I get different memory addresses:</p>
  
  <pre><code>print $new_basket, "\n";
  print $basket{ident $self}, "\n";
  print $new_basket-&gt;{auto}-&gt;{items}, "\n";
  print $basket{ident $self}{auto}-&gt;{items}, "\n";
  print $new_basket-&gt;{auto}-&gt;{items}-&gt;{abc}, "\n";
  print $basket{ident $self}{auto}-&gt;{items}-&gt;{abc}, "\n";
  </code></pre>
  
  <p>this will output:</p>
  
  <pre><code>HASH(0x55d325306a20)
  HASH(0x55d325245298)
  HASH(0x55d323b35ca8)
  HASH(0x55d3243dd968)
  Item=SCALAR(0x55d323b45190)
  Item=SCALAR(0x55d325306588)
  </code></pre>
  
  <p>When I don't use <code>dclone</code> and use <code>my $new_basket = $basket{ident $self}</code> instead, I get the same memory addresses. When I use <code>my $new_basket = { %{ $basket{ident $self} } }</code>, I get different addresses only on the first level, which should be a shallow copy. All this seems fine and expected.</p>
  
  <p>So, to me it seems that <code>dclone</code> actually deep-copied everything because the addresses are different. But when I try to use a method inside <code>Item</code> like so:</p>
  
  <pre><code>print $new_basket-&gt;{auto}-&gt;{items}-&gt;{abc}-&gt;get_added_on();
  print $basket{ident $self}{auto}-&gt;{items}-&gt;{abc}-&gt;get_added_on();
  </code></pre>
  
  <p>I get:</p>
  
  <pre><code>Use of uninitialized value in print at lib/Basket.pm line 231.
  2020-05-30
  </code></pre>
  
  <p>clearly that <code>dclone</code> works differently than I naively thought.</p>
  
  <p><strong>How should I deep-copy this whole structure?</strong> I'd appreciate some help or reference to some article/doc where I can read what's going on here.</p>
  
  <p>One solution is to create the whole structure again using constructors, but I thought I'd save some space and use dclone. That obviously didn't turn out very well.</p>
  
  <p><strong>EDIT:</strong> I've been asked to provide a minimal runnable demonstration, here it is:</p>
  
  <pre><code>#!/usr/bin/env perl
  
  use strict;
  use warnings;
  
  {
      package A;
      use Class::Std;
      use Data::Dumper;
      use Storable qw(dclone);
  
      my %basket :ATTR;
  
      sub BUILD {
          my ($self, $ident, $args_ref) = @_;
          $basket{$ident}-&gt;{auto} = {};
  
          my $c = C-&gt;new({ date =&gt; q{2020-05-30} }); 
  
          $basket{$ident}-&gt;{auto}-&gt;{items}-&gt;{abc} = $c;      
  
          return;
      }
  
      sub deep_clone {
          my $self = shift;
  
          print Dumper $basket{ident $self};
          # the next line prints "2020-05-30" as expected
          print $basket{ident $self}-&gt;{auto}-&gt;{items}-&gt;{abc}-&gt;get_added_on();
          my $new_basket = dclone $basket{ident $self};
          # "Use of uninitialized value in print at ./deep-clone.pl line 35."
          print $new_basket-&gt;{auto}-&gt;{items}-&gt;{abc}-&gt;get_added_on();
      }
  }
  
  {
      package C;
      use Class::Std;
  
      my %added_on :ATTR( :get&lt;added_on&gt; );
  
      sub BUILD {
          my ($self, $ident, $args_ref) = @_;
  
          $added_on{$ident} = $args_ref-&gt;{date};
  
          return;
      }
  }
  
  ####
  
  my $a = A-&gt;new();
  $a-&gt;deep_clone();
  </code></pre>