garu / Data-Printer

colored pretty-print of Perl data structures and objects
100 stars 81 forks source link

Incorrect output with tied hashes #170

Closed Ovid closed 1 year ago

Ovid commented 2 years ago

Hi there. With tied hashes, the output appears to be incorrect. I've included a _data_printer method in my class and all values are reported as being the same as the first value:

For this minimal test case, I've created a simple tied hash which calls scalar reverse on all hash values before storing them. I then dump two identical hashes, with the first hash being tied. The second hash is built with the values of the first. The output is:

{
    first    4321,
    second   var{first},
    third    var{first}
} (tied to Tie::Me::Up)
{
    first    4321,
    second   "DCBA",
    third    "?ftw"
}

Here's my sample code:

#!/usr/bin/env perl

use warnings;
use Data::Printer;

package Tie::Me::Up {
    use v5.20.0;
    use feature 'signatures';
    no warnings 'experimental::signatures';

    sub TIEHASH ( $class, $generator ) {
        return bless {
            generator => $generator,
            hash      => {},
        }, $class;
    }

    sub FETCH ( $self, $key ) {
        return $self->{hash}{$key};
    }

    sub STORE ( $self, $key, $value ) {
        $self->{hash}{$key} = $self->{generator}->($value);
    }

    sub DELETE ( $self, $key ) {
        return delete $self->{hash}{$key};
    }

    sub CLEAR ($self) {
        $self->{hash} = {};
    }

    sub EXISTS ( $self, $key ) {
        return exists $self->{hash}{$key};
    }

    sub FIRSTKEY ($self) {
        keys %{ $self->{hash} };    # reset each() iterator
        each %{ $self->{hash} };
    }

    # lastkey is here for documentation, but we don't use it
    sub NEXTKEY ( $self, $lastkey ) {
        return each %{ $self->{hash} };
    }

    sub SCALAR ($self) {
        return scalar keys %{ $self->{hash} };
    }

    sub _data_printer ( $self, @ ) {

        # it doesn't matter if I return a list or a hashref
        # return %{ $self->{hash} };
        return $self->{hash};
    }

    # DESTROY this is not needed
    # UNTIE this is not needed
}

sub munger {
    my ( $key, @args ) = @_;
    return "Stored: " . join '-', $key, @args;
}

tie my %hash, 'Tie::Me::Up', sub { return scalar reverse $_[0] };
$hash{first}  = '1234';
$hash{second} = 'ABCD';
$hash{third}  = 'wtf?';
my %hash_2 = (
    first  => $hash{first},
    second => $hash{second},
    third  => $hash{third},
);
p %hash;
p %hash_2;

Note that Tie::Me::Up includes several methods not needed for this example, but I wanted to be complete, in case you needed to test other scenarios.

Perl info (built via bog-standard perlbrew setup):

07:29:07 {main} ~/projects/perl/lazy-variables $ perl -v

This is perl 5, version 26, subversion 3 (v5.26.3) built for darwin-2level
(with 1 registered patch, see perl -V for more detail)
garu commented 1 year ago

Hi Ovid! Sorry for the long wait. This should be fixed in v1.1.1, already on its way to CPAN. Please let me know if any other issues arise.

Ovid commented 1 year ago

@garu Thanks for fixing it! No worries about the delay. I'm a master of not noticing bug reports 😃