How do you dump an object instance with Perl's new class feature?
Asked Answered
P

3

6

The goal is to see the encapsulated data, like I've been doing for the last 26 years.

use 5.040;
use strictures;
use experimental 'class';

class Foo {
    field @member = qw(e r t);
}

my $foo = Foo->new;

# use Data::Dumper qw(Dumper);
# say Dumper $foo;
# cannot handle ref type 16

# use DDS; DumpLex $foo;
# _dump_rv() can't handle 'OBJECT' objects yet

# use Data::Dx; Dx $foo;
# Can't handle OBJECT data

# use DDP; p $foo;
# Foo  {
#     public methods (1): new
#     private methods (0)
#     internals: (opaque object)
# }
#                ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
Pirogue answered 28/5, 2024 at 9:24 Comment(0)
W
3

The Tuple::Munge package on CPAN might help you.

use v5.38;

sub tuple_to_aref ( $t ) {
    use Tuple::Munge ();
    use experimental 'builtin';
    use builtin 'blessed';
    my $len = Tuple::Munge::tuple_length($t);
    my $aref = [ map Tuple::Munge::tuple_slot($t, $_-1), 1 .. $len ];
    if ( my $class = blessed $t  ) {
        return bless( $aref, "TUPLE_TO_ARRAY::$class" );
    }
    return $aref;
}

use experimental 'class';
use Data::Dumper;

class My::Class {
    field $x;
    ADJUST {
        $x = 'Foobar';
    }
}

my $object = My::Class->new;
print Dumper( tuple_to_aref( $object ) );

Sample output:

$VAR1 = bless( [
                 \'Foobar'
               ], 'TUPLE_TO_ARRAY::My::Class' );
Woodsy answered 13/6, 2024 at 9:23 Comment(3)
This does give you an array ref, but it doesn't tell you which field the array element belongs to. It's better than nothing, but for a moderately complex object this is unsatisfying. You might consider showing the output of your program so people can see what they are actually getting.Marden
It not saying what field the array element belongs to is something it has in common with any non-hashref Perl objects, for example ones based around blessed arrayrefs. Added a sample of the output though.Woodsy
If I choose to use an array ref as the basis for my object, I get to pick the order of the elements. And, people can inspect the source to see what went where. With the new object stuff, not so much.Marden
M
5

If you want to use class which is intentionally designed to not let you look at its innards, you don't get to dump it with external modules either. You'll have to add something in the class to dump things, which is a lot of extra work. Overall I don't think that class is a good idea, and this sort of roadblock to practical development is one of the reasons I think that.

Marden answered 28/5, 2024 at 12:40 Comment(0)
C
3

I also see the lack of an inspection interface as an obstacle to use the 'class' feature in my projects.

Generic support by debuggers and dumpers is not impossible, though. It will just have to wait until a meta object protocol (MOP) for the 'class' feature is available. There's still work to do after that, of course, to use it.

For the CPAN module Object::Pad which is sort of a testbed for the feature, there is a MOP, and basic support by Data::Printer. There's also a proof of concept how to inspect Object::Pad objects with the Perl debugger.

Of the available modules, Data::Dumper is not a good candidate to inspect encapsulated class data: Per widespread habit, it delivers valid Perl code which can constructs the data. That, however, is not generally possible with 'class' type objects, nor with Object::Pad objects. Modules which are not bound by the expectation to do round-trips would just need to implement the MOP.

Coleen answered 28/5, 2024 at 13:22 Comment(2)
Data::Dumper outputs Perl code because that's what it does, not because of habit or some weird way that people are misusing it. But even though, Data::Dumper has served people quite well for decades, hence the question.Marden
Sorry if that came out wrong: I did not want to imply misuse or weirdness. Data::Dumper and two of the listed alternatives, DDS and Data::Dx, use Perl code as their output format. The innards of "class" objects can not be displayed as valid Perl code. However, humans do not necessarily need Perl code to see the encapsulated data. That's why modules like DDP which don't output Perl code are better suited to solve the OP's problem.Coleen
W
3

The Tuple::Munge package on CPAN might help you.

use v5.38;

sub tuple_to_aref ( $t ) {
    use Tuple::Munge ();
    use experimental 'builtin';
    use builtin 'blessed';
    my $len = Tuple::Munge::tuple_length($t);
    my $aref = [ map Tuple::Munge::tuple_slot($t, $_-1), 1 .. $len ];
    if ( my $class = blessed $t  ) {
        return bless( $aref, "TUPLE_TO_ARRAY::$class" );
    }
    return $aref;
}

use experimental 'class';
use Data::Dumper;

class My::Class {
    field $x;
    ADJUST {
        $x = 'Foobar';
    }
}

my $object = My::Class->new;
print Dumper( tuple_to_aref( $object ) );

Sample output:

$VAR1 = bless( [
                 \'Foobar'
               ], 'TUPLE_TO_ARRAY::My::Class' );
Woodsy answered 13/6, 2024 at 9:23 Comment(3)
This does give you an array ref, but it doesn't tell you which field the array element belongs to. It's better than nothing, but for a moderately complex object this is unsatisfying. You might consider showing the output of your program so people can see what they are actually getting.Marden
It not saying what field the array element belongs to is something it has in common with any non-hashref Perl objects, for example ones based around blessed arrayrefs. Added a sample of the output though.Woodsy
If I choose to use an array ref as the basis for my object, I get to pick the order of the elements. And, people can inspect the source to see what went where. With the new object stuff, not so much.Marden

© 2022 - 2025 — McMap. All rights reserved.