http://www.perlmonks.org?node_id=814482

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

I am using Data Dumper to send a perl hash ref from one server to another. Works great but for one weird thing. When I setup some hash refs i see something like this:
$VAR1 = { 'test1' => [ { 'temp' => '123' } ], 'test2' => [ $VAR1->{'test1'}[0] ] };
Where you see VAR1 I would like to find a way for this to just show the correct data instead of the reference. The code might help you understand more seeing the output.
#!/usr/bin/perl use strict; use Data::Dumper; my ($hash_ref, $var1); print "This is my test of Data Dummper\n"; ## Setup Data $var1->{temp} = "123"; push (@{$hash_ref->{test1}}, $var1); push (@{$hash_ref->{test2}}, $var1); print Dumper($hash_ref); ## print new data my $VAR1; eval Dumper($hash_ref); print Dumper($VAR1); exit;
Full output
$VAR1 = { 'test1' => [ { 'temp' => '123' } ], 'test2' => [ $VAR1->{'test1'}[0] ] }; $VAR1 = { 'test1' => [ { 'temp' => '123' } ], 'test2' => [ undef ] };
As you can see test2 is undef instead of saying temp => '123'. Is there a way to fix this? thanks

Replies are listed 'Best First'.
Re: Data Dumper Question
by ikegami (Patriarch) on Dec 27, 2009 at 07:23 UTC

    [ I had this written before an internet outage. I might as well still post it even though something similar was already posted. ]

    First, the solution is to set Purity

    #!/usr/bin/perl use strict; use Data::Dumper; my $var1 = { temp => "123" }; my $hash_ref; push @{$hash_ref->{test1}}, $var1; push @{$hash_ref->{test2}}, $var1; print Dumper($hash_ref); my $dump = do { local $Data::Dumper::Purity = 1; Dumper($hash_ref); }; my $VAR1; eval "$dump; 1" or die $@; print Dumper($VAR1);
    $VAR1 = { 'test1' => [ { 'temp' => '123' } ], 'test2' => [ $VAR1->{'test1'}[0] ] }; $VAR1 = { 'test1' => [ { 'temp' => '123' } ], 'test2' => [ $VAR1->{'test1'}[0] ] };

    But really, Data::Dumper is not the right tool. Storable can best represent Perl data structures. If you want something human-readable, both JSON and YAML cover all the basics.

Re: Data Dumper Question
by Khen1950fx (Canon) on Dec 27, 2009 at 07:51 UTC
    I went along a different route:

    #!/usr/bin/perl use strict; use warnings; use Data::Dumper; my ($hash_ref, $var1, $var2); print "\n------This is my test of Data Dumper------\n\n"; $var1->{'temp'} = '123'; push (@{$hash_ref->{'test1'}}, $var1); push (@{$hash_ref->{'test2'}}, $var1); warn Dumper($hash_ref); $var2->{'temp2'} = '123'; warn Dumper($hash_ref), "\n\n"; print "----------------------------------------------\n"; exit;
    Update: Using Data::Dump::Streamer instead:

    #!/usr/bin/perl use strict; use warnings; use Data::Dump::Streamer; my ($hash_ref, $var1, $var2); print "\n------This is my test of Data Dumper------\n\n"; $var1->{'temp'} = '123'; push (@{$hash_ref->{'test1'}}, $var1); push (@{$hash_ref->{'test2'}}, $var1); warn Dump($hash_ref); $var2->{'temp2'} = '123'; warn Dump($hash_ref), "\n\n"; print "----------------------------------------------\n"; exit;
Re: Data Dumper Question
by McDarren (Abbot) on Dec 27, 2009 at 07:11 UTC
Re: Data Dumper Question
by JadeNB (Chaplain) on Dec 27, 2009 at 22:36 UTC

    Others have pointed out how to make the behaviour conform to your expectations; but I wanted to point out that ‘fix’ may not be the right term, since Data::Dumper is correctly indicating to you that your $hashref->{test1} and $hashref->{test2} are not just 2 references to similar hashes, but literally the same hashref. You can demonstrate this to yourself:

    $hashref->{test1}{temp}[0] = 456; print $hashref->{test2}{temp}[0]; # => 456
    This is the classical problem of deep versus shallow copies.

    The reason that you don't get the desired behaviour when you eval the output of Dumper is that the eval happens “all at once”—when the ‘inner’ reference to $VAR1->{test1}{temp}[0] is being evaluated, $VAR1 doesn't yet have the value that it will have when the eval completes, so all you're doing is auto-vivifying it as a reference to a hash-of-hashes-of-arrays. Accessing the 0th entry of that innermost array makes sure that it exists, but doesn't assign it a value, so it comes out undef. The documentation for Data::Dumper warns of this (but, in my opinion, not very clearly), and mentions the solution that ikegami already gave:

    The default output of self-referential structures can be evaled, but the nested references to $VARn will be undefined, since a recursive structure cannot be constructed using one Perl statement. You should set the Purity flag to 1 to get additional statements that will correctly fill in these references. Moreover, if evaled when strictures are in effect, you need to ensure that any variables it accesses are previously declared.

      Thanks for all your help! this did fix my problem!
Re: Data Dumper Question
by Anonymous Monk on Dec 27, 2009 at 06:14 UTC
    use our $VAR1, or better yet, use JSON :)
      I see what you saying about using our, but it didnt seem to make a difference.
        $ perldoc Data::Dumper |grep eval printing and "eval" eval Data::Dumper->Dump([$foo, $bar], [qw(foo *ary)]); eval $d->Dump; The return value can be "eval"ed to get back an identical copy of +the The default output of self-referential structures can be "eval"ed, + but fill in these references. Moreover, if "eval"ed when strictures ar +e in Controls the degree to which the output can be "eval"ed to rec +reate output may not always be parseable by "eval". $bar = eval(Dumper($boo)); $Data::Dumper::Purity = 1; # fill in the holes for eva +l $d = eval $c; if "Purity" is set. You can "eval" the result, but bear in mind th +at the
        $Data::Dumper::Purity = 1; makes it write
        $VAR1 = { 'test1' => [ { 'temp' => '123' } ], 'test2' => [ {} ] }; $VAR1->{'test2'}[0] = $VAR1->{'test1'}[0];
        You could use YAML
Re: Data Dumper Question
by planetscape (Chancellor) on Dec 28, 2009 at 00:54 UTC