Arry
Arry

Reputation: 1035

How to make Data::Printer show stringified values in internals?

I have some complex object structures, and I use Data::Printer to inspect them. One case where it's not helpful enough is this: when an object (container) has a field that's another object (child), the child shows up in DDP's output only as class name. I wish to also see the stringified value of the child.

Let's have an example:

{
    package Child;
    use Moo;

    use overload '""' => "stringify";

    has 'value', is => 'ro';

    sub stringify {
        my $self = shift;
        return "<Child:" . $self->value . ">";
    }

}

{
    package Container;
    use Moo;

    has 'child', is => 'ro';
}

my $child_x = Child->new(value => 'x');
print "stringified child x: $child_x\n";

my $child_y = Child->new(value => 'y');
print "stringified child y: $child_y\n";

my $container_x = Container->new(child => $child_x);
my $container_y = Container->new(child => $child_y);

use DDP;
print "ddp x: " . p($container_x) . "\n";
print "ddp y: " . p($container_y) . "\n";

Output:

stringified child x: <Child:x>
stringified child y: <Child:y>
ddp x: Container  {
    Parents       Moo::Object
    public methods (2) : child, new
    private methods (0)
    internals: {
        child   Child                  # <- note this
    }
}
ddp y: Container  {
    Parents       Moo::Object
    public methods (2) : child, new
    private methods (0)
    internals: {
        child   Child                  # <- and this
    }
}

As you see, the children are indistinguishable in the output. I'd like to see the stringification in that place, either in addition to or instead of the class name.

Upvotes: 1

Views: 141

Answers (2)

Arry
Arry

Reputation: 1035

As Dave pointed out, we can define the filter when importing Data::Printer:

use DDP filters => {
    'Child' => sub { "$_[0]" }
};

And even better way would be to use the _data_printer feature (because it's a pain to type out the filters definition every time I import DDP):

{
    package Child;
    ...

    sub _data_printer {
        my $self = shift;
        return "$self";
    }
}

Both ways display the stringified value in internals:

ddp x: Container  {
    Parents       Moo::Object
    public methods (2) : child, new
    private methods (0)
    internals: {
        child   <Child:x>
    }
}

Upvotes: 2

Dave Sherohman
Dave Sherohman

Reputation: 46225

Per the Data::Printer docs,

Data::Printer offers you the ability to use filters to override any kind of data display. The filters are placed on a hash, where keys are the types - or class names - and values are anonymous subs that receive two arguments: the item itself as first parameter, and the properties hashref (in case your filter wants to read from it). This lets you quickly override the way Data::Printer handles and displays data types and, in particular, objects.

Upvotes: 2

Related Questions