Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Dumping opaque objects

by hv (Prior)
on Jan 23, 2022 at 22:52 UTC ( [id://11140754]=perlquestion: print w/replies, xml ) Need Help??

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

A bit too often I write some code, have a problem, stick in a temporary Data::Dumper call, and see something like this:

sub munge_data { my($data) = @_; # temp hack use Data::Dumper; warn Dumper($data); ... # do munging } ... $VAR1 = [ bless( do{\(my $o = 63036880)}, 'Math::GMP' ), bless( do{\(my $o = 63024960)}, 'Math::GMP' ), bless( do{\(my $o = 63021408)}, 'Math::GMP' ) ],

Now Data::Dumper has the Freezer interface, which provides a way to modify the object before dumping - useful if the object caches a bunch of verbose but uninteresting stuff which will automatically be recreated when needed.

What Data::Dumper doesn't seem to provide is a way to say "call this method/function to get the _actual string_ this object should dump as". For this case it would be ideal to represent a GMP object $z as something like "z$z", taking advantage of its existing stringification overload - despite Data::Dumper's stated purpose, I hardly ever care about evalling the output to recreate the data structure.

Does anyone know of a recommended (or remotely usable) way to achieve such a thing? Ideal would be a per-class override, but even a global one would nearly always be as useful to me.

Update: I'm perfectly happy to use a module other than Data::Dumper, clearly that wasn't clear.

Update: I've managed to make some progress with Data::Printer after a few false starts. I'm going to spend some time seeing if I can learn to live with its output format (which has lots of options, but not necessarily the ones I'd want), but I like that I can throw almost everything in a config file so there's minimal boilerplate when I use it:

% cat ~/.dataprinter use_prototypes = 0 index = 0 align_hash = 0 hash_separator = ' => ' colored = 0 begin filter Math::GMP $ddp->unsee($obj); "z_$obj"; end filter % perl -MDDP -MMath::GMP -we ' $val = 1; $zval = Math::GMP->new(1); p [$val, $val, $zval, $zval]; ' [ 1, 1, z_1, z_1 ] %

The hardest bit was avoiding its handling of duplicate references, which was making the last line of output show var[2] instead of z_1. That's what the unsee() call is fixing for me.

Replies are listed 'Best First'.
Re: Dumping opaque objects
by haukex (Archbishop) on Jan 24, 2022 at 17:43 UTC

    Since further down in the thread you seem to say that other modules would be acceptable: I use Data::Dump::Filtered for these kind of things. Since in this case Math::GMP deals with integers, I think it's probably safe to not worry about escaping the stringified objects, but in theory one could use the pp function for escaping values as well.

    use warnings; use strict; use Math::GMP; use Data::Dump qw/dd pp/; use Data::Dump::Filtered qw/add_dump_filter/; add_dump_filter( sub { my ($ctx, $objref) = @_; return { dump => "Math::GMP->new(\"$objref\")" } if $ctx->object_isa('Math::GMP'); return; # normal dumping } ); dd( Math::GMP->new("123"), Math::GMP->new("546745634563453111035453452346") ); __END__ ( Math::GMP->new("123"), Math::GMP->new("546745634563453111035453452346"), )

      One's reminded of (well, I was at least) prin1 and friends in Lisp. There's a princ that's meant for displaying things in a pretty notation for hyooman consumption, whereas prin1 produces something that the read function could conceivably re-ingest and produce an equivalent value.

      The cake is a lie.
      The cake is a lie.
      The cake is a lie.

      Thanks, and sorry I wasn't clear - I was absolutely expecting that the solution would need some other module, that's certainly acceptable. I've added a note to that effect on the OP.

      I'll have to have a play with this - I guess I skipped past it too quickly when looking at the Data::Dump docs, possibly because the only mention I saw there was the unwieldy-seeming dumpf(..., \&filter).

Re: Dumping opaque objects
by Anonymous Monk on Jan 23, 2022 at 23:44 UTC
    ...Freezer = 'stringify'; local *UNIVERSAL::stringify = sub { $_[0]->isa('Math::GMP') ? "$_[0]" : $_[0] }; ...Dumper...

      Sadly that doesn't appear to do what I want (though I'd love it to): the docs for $Data::Dumper::Freezer talk only about modifying the object passed in, not about a return value. And indeed, trying it (with a different name to avoid the existing Math::GMP::stringify method) shows it is called but has no effect on the Data::Dumper output:

      % perl -MData::Dumper -MMath::GMP -wle ' $Data::Dumper::Freezer = "zify"; local *UNIVERSAL::zify = sub { warn "zify $_[0]"; $_[0]->isa("Math:: +GMP") ? "z$_[0]" : $_[0] }; my $x = [ Math::GMP->new(1) ]; print "x[0]=$x->[0]"; print Dumper($x); print "x[0]=$x->[0]"; ' Name "UNIVERSAL::zify" used only once: possible typo at -e line 3. x[0]=1 zify 1 at -e line 3. $VAR1 = [ bless( do{\(my $o = 40040032)}, 'Math::GMP' ) ]; x[0]=1

      If I change it to assign back to $_[0] instead, Dumper outputs garbage ("\undef") and the data structure is corrupted to have the new string instead of the original object:

      % perl -MData::Dumper -MMath::GMP -wle ' $Data::Dumper::Freezer = "zify"; local *UNIVERSAL::zify = sub { warn "zify $_[0]"; $_[0]->isa("Math:: +GMP") ? "z$_[0]" : $_[0] }; my $x = [ Math::GMP->new(1) ]; print "x[0]=$x->[0]"; print Dumper($x); print "x[0]=$x->[0]"; ' Name "UNIVERSAL::zify" used only once: possible typo at -e line 1. x[0]=1 zify 1 at -e line 1. $VAR1 = [ \undef ]; x[0]=z1
        Hi hv,

        I was able to get a Dumper() that appears more meaningful (to me, at least) with:
        ## dumper.pl ## use strict; use warnings; use Data::Dumper; use Math::GMP; my $x = [ Math::GMP->new(101), Math::GMP->new(203), Math::GMP->new(116 +7) ]; print Dumper("@$x"); __END__ C:\_32\pscrpt>perl dumper.pl $VAR1 = '101 203 1167';
        However, I'm not familiar with Data::Dumper and I've no idea if that's of any use to you.

        Cheers,
        Rob

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11140754]
Approved by kcott
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (3)
As of 2024-04-25 07:44 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found