It doesn't look very elegant.

Checking the reference type twice is not elegant. More importantly, it doesn't work since you only handle HASH (and not ARRAY and non-refs) at the outer level.

_iterative_copy( [ 'a' ] );

outputs

What's a ARRAY at script.pl line 12 main::_iterative_copy('ARRAY(0x15d5f18)') called at script.pl +line 47

Working code:

use strict; use warnings; use Data::Dumper qw( Dumper ); sub iterative_copy { my $root; my @src; my @dst; push @src, $_[0]; push @dst, \$root; while (@src) { my $src = shift(@src); my $dst = shift(@dst); if (not ref $src) { $$dst = $src; } elsif (ref $src eq "HASH") { $dst = ($$dst = {}); foreach my $key (keys %$src) { push @src, $src->{$key}; push @dst, \($dst->{$key}); } } elsif (ref $src eq "ARRAY") { $dst = ($$dst = []); foreach my $i (0..$#$src) { push @src, $src->[$i]; push @dst, \($dst->[$i]); } } else { Carp::croak "What's a " . ref $_ . "?" } } return $root; } { local $Data::Dumper::Indent = 0; my $d1 = [ [ 'a', 'b' ], { k1=>'v1', k2=>'v2' } ]; my $d2 = iterative_copy($d1); print(Dumper($d1), "\n"); print(Dumper($d2), "\n"); print($d1, " != ", $d2, "\n"); print($d1->[0], " != ", $d2->[0], "\n"); print($d1->[1], " != ", $d2->[1], "\n"); }

Output:

$VAR1 = [['a','b'],{'k2' => 'v2','k1' => 'v1'}]; $VAR1 = [['a','b'],{'k2' => 'v2','k1' => 'v1'}]; ARRAY(0x1ae0718) != ARRAY(0x1ae073c) ARRAY(0x15d5fd8) != ARRAY(0x1ae076c) HASH(0x15d6c98) != HASH(0x1ae0790)

Below is a more elegant version. It uses one array (@todo) instead of two (@src, @dst). However, it uses more memory.


In reply to Re: Iteratively deep copying a data structure by ikegami
in thread Iteratively deep copying a data structure by telcontar

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.