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

Hello,
in the aim to add 'aliases' to a dispatch table i encountered something i do not understand in the output created by Data::Dumper.
the following code:
#!perl use strict; use warnings; use Data::Dumper; $Data::Dumper::Purity =1; my %dispatch = ( original_a => sub {print "AAA\n"}, ); $dispatch{a}=\&{$dispatch{original_a}}; print Dumper(\%dispatch);
prints an inverted result:
Encountered CODE ref, using dummy placeholder at C:/Perl/lib/Data/Dump +er.pm line 179. $VAR1 = { 'a' => sub { "DUMMY" }, 'original_a' => do{my $o} }; $VAR1->{'original_a'} = $VAR1->{'a'};
I was expecting that 'original_a' was sub { "DUMMY" } and not do{my $o}. The inversion is reaffermed using $Data::Dumper::Purity =1; that prints the last line $VAR1->{'original_a'} = $VAR1->{'a'};

The following oneliner,by other hand, runs as expected:
perl -MData::Dumper -e "$h{a} = sub{print qq(AAA\n)}; $h{alias} = \&{$ +h{a}}; print Dumper(\%h)" $VAR1 = { 'a' => sub { "DUMMY" }, 'alias' => $VAR1->{'a'} };

What i'm missing? What is happening?

Thanks
L*
There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

Replies are listed 'Best First'.
Re: doubts about Data::Dumper output
by choroba (Cardinal) on Oct 06, 2014 at 10:10 UTC
    Hash keys are not ordered. It is irrelevant which one will be defined first. In the end, they both point to the same code reference.

    BTW, you can simplify the assignment by dropping the cast and dereference:

    $dispatch{a} = $dispatch{original_a};
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: doubts about Data::Dumper output
by LanX (Saint) on Oct 06, 2014 at 11:27 UTC
    Dumping code refs isn't trivial, that's why dummies are used.

    Data::Dump for instance tries to use B::Deparse which isn't 100% correct (only the OP tree can be, think closures)

    Choroba already explained that hashes have no order you can rely on.

    The only unexpected thing here is that two examples produced different dump strategies... But both seem correct.

    Cheers Rolf

    (addicted to the Perl Programming Language and ☆☆☆☆ :)

Re: doubts about Data::Dumper output
by MidLifeXis (Monsignor) on Oct 06, 2014 at 13:12 UTC

    The one-liner does not set Purity. Purity will cause a dummy placeholder to be generated in the second reference and a cleanup statement after. The do... stuff is just a placeholder until the cleanup happens.

    In the one liner, the module does not care if the structure can be reconstituted properly -- it is just showing a person the logical structure of the data. Once Purity is set, then the data can actually be regenerated (other than the actual SUB contents). To facilitate this, a unique junk value needs to be generated, which is where the do{...} block comes in. Line 6 in your second snippet is where the cleanup happens, removing the junk value created by the do and replacing it with the same reference to the sub that is present when the reconstituted hash is created (lines 2-5, second code block).

    (Update) Since, as has been previously mentioned, hashes are unordered, it really doesn't matter which is created first. It appears that the hash keys are sorted, but this may just be due to chance. The reconstituted data structure would be identical once the Purity-generated data has been executed.

    --MidLifeXis

      Until the verbose answer of LanX and MidLifeXis i was not understanding the 'unordered keys' argument.

      Now it appears clear: the reference count! Two pointers share the same address: how can Data::Dumper or any other module tell who was set before?

      In such perspective the module behaviour had to expected in advance.

      Sometime trees conceal the wood.

      thanks
      L*
      There are no rules, there are no thumbs..
      Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: doubts about Data::Dumper output
by Anonymous Monk on Oct 06, 2014 at 10:15 UTC

    What i'm missing? What is happening?

    A peek at Dumper.pm reveals that line is return &Dumpxs and thats all like XS and stuff :) so its a bug in the XS version I reckon so you can perlbug it

    Data::Dump doesn't warn about it ... of course it doesn't deparse

    do { my $a = { a => sub { ... }, original_a => 'fix' }; $a->{original_a} = $a->{a}; $a; }

    Data::Dump::Streamer Deparse-s fine

    $HASH1 = { a => sub { use warnings; use strict; print "AAA\n"; }, original_a => 'V: $HASH1->{a}' }; $HASH1->{original_a} = $HASH1->{a};

    Bug #122111 for perl5: Data::Dumper vul'n reported

Re: doubts about Data::Dumper output
by Discipulus (Canon) on Oct 06, 2014 at 11:40 UTC
    dunno if i understand the Anonymous's answer..

    BTW even Data::Dump::Streamer seems offer the same result: ie original_a pointing to alias (and not vice-versa)
    #!perl use strict; use warnings; use Data::Dump::Streamer; my %dispatch = ( original_a => sub {print "AAA\n"}, ); $dispatch{alias}=\&{$dispatch{original_a}}; print Dump(\%dispatch); #OUTPUT $HASH1 = { alias => sub { use warnings; use strict 'refs'; print "AAA\n"; }, original_a => 'V: $HASH1->{alias}' }; $HASH1->{original_a} = $HASH1->{alias};


    thanks
    L*
    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
      Please read Choroba's answer again, hashes have no order!

      You can't control which key is processed first by dumper.

      And both keys point to the same ref!

      You are expecting dumper to parse your original code to figure out which order was meant, but this information is lost within the hash!

      Cheers Rolf

      (addicted to the Perl Programming Language and ☆☆☆☆ :)

      dunno if i understand the Anonymous's answer...

      Ok, elaboration, Data::Dumper::Dumpxs() does the actual Dumpering ... and it emits a warning and does a bad job of Dumping the code reference.

      This is a genuine perlbug you found, you should report it -- as the link I linked earlier shows, bugs in Dumper can happen, if you report it, it will probably be fixed

      Streamer does a good job of dumping the code reference

      About the order, yeah, hashes are "unordered" what choroba/LanX said :) .... Data::Dumper does have a Sortkeys option .... as there is https://metacpan.org/pod/Data::Dump::Streamer#Controlling-Hash-Traversal-and-Display-Order

      Yes, lets burn some wood :) its a renewable resource

        I'm not sure what bug you're talking about. The fact that Data::Dumper can't dump code references is documented:
        "Data::Dumper" cheats with CODE references. If a code reference is encountered in the structure being processed (and if you haven't set the "Deparse" flag), an anonymous subroutine that contains the string '"DUMMY"' will be inserted in its place, and a warning will be printed if "Purity" is set.
        لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
        About $Data::Dumper::Sortkeys: this seems to be unrelated in this case: it can force the default Perl ordering about keys or a special ordering providing a subroutine. Nothing to do with the order reference are created.

        thanks
        L*

        There are no rules, there are no thumbs..
        Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.