Data-Dumper-Names

 view release on metacpan or  search on metacpan

lib/Data/Dumper/Names.pm  view on Meta::CPAN

package Data::Dumper::Names;

use warnings;
use strict;

use Data::Dumper ();
use Scalar::Util 'refaddr';
use PadWalker 'peek_my';
use base 'Exporter';
our @EXPORT  = qw/Dumper/;
our $UpLevel = 1;

=head1 NAME

Data::Dumper::Names - Dump variables with names (no source filter)

=head1 VERSION

Version 0.03

=cut

our $VERSION = '0.03';

=head1 SYNOPSIS

    use Data::Dumper::Names;

    my $foo = 3;
    my @bar = qw/this that/;
    warn Dumper($foo, \@bar);
    __END__
    output:
    
    $foo = 3;
    @bar = (
        'this',
        'that'
    );

=head1 EXPORT

Like L<Data::Dumper>, this module automatically exports C<Dumper()>
unless a null import list is explicitly stated.

This module should be considered ALPHA.

=head1 FUNCTIONS

=head2 Dumper

 warn Dumper($foo, \@bar);

C<Dumper> returns a string like C<Dumper> but the variable names are prefixed
for you.  Unlike L<Data::Dumper::Simple>, arrays and hashes must be passed by
reference.

=cut

sub Dumper {
    my $pad = peek_my($UpLevel);
    my %pad_vars;
    while ( my ( $var, $ref ) = each %$pad ) {

        # we no longer remove the '$' sigil because we don't want
        # "$foo = \@array" reported as "@foo".
        $var =~ s/^[\@\%]/*/;
        $pad_vars{ refaddr $ref } = $var;
    }
    my @names;
    my $varcount = 1;
    foreach (@_) {
        my $name;
        INNER: foreach ( \$_, $_ ) {
            no warnings 'uninitialized'; 
            $name = $pad_vars{ refaddr $_} and last INNER;
        }
        push @names, $name;
    }

    return Data::Dumper->Dump( \@_, \@names );
}

=head1 CAVEATS

=head2 PadWalker

This module is an alternative to L<Data::Dumper::Simple>.  Many people like
the aforementioned module but do not like the fact that it uses a source
filter.  In order to pull off the trick with this module, we use L<PadWalker>.
This introduces its own set of problems, not the least of which is that
L<PadWalker> uses undocumented features of the Perl internals and has an
annoying tendency to break.  Thus, if this module doesn't work on your
machine you may have to go back to L<Data::Dumper::Simple>.

=head2 References

Arrays and hashes, unlike in L<Data::Dumper::Simple>, must be passed by
reference.  Unfortunately, this causes a problem:

 my $foo = \@array;
 warn Dumper( $foo, \@array );

Because of how pads work, there is no easy way to disambiguate between these
two variables.  Thus, C<Dumper> may identify them as C<$foo> or it may
identify them as C<@array>.  If it misidentifies them, it should at least do
so consistently for the individual call to C<Dumper>.  (For Perl 5.8 and
after, subsequent calls to C<Dumper> may have different results in the above
case.  This is because of how Perl handles hash ordering).

=head2 Call stack level

You generally will call things with this:

 warn Dumper($foo, $bar, \@baz);

However, you might be refactoring code and want to shove that into a
subroutine somewhere.  In that case, you'll need to set (via C<local>!), the
$Data::Dumper::Names::UpLevel variable.  It defaults to one, but you might set
it to a higher level, depending on how high up the call stack those variables
are really located:

 sub show {
     return unless $ENV{VERBOSE};
     local $Data::Dumper::Names::UpLevel = 2;
     warn Dumper(@_);
 }

Note that if you fail to use C<local>, subsequent calls to C<Dumper> may be
looking at the wrong call stack level.

=head2 Unknown Variables

The easiest way to have things "just work" is to make sure that you can
see the name of the variable in the C<Dumper> call:

 warn Dumper($foo, \@bar); # good
 warn Dumper($_);          # probably will get output like $VAR1 = ...
 warn Dumper($bar[2]);     # probably will get output like $VAR1 = ...

Usually the output from L<Dumper> will be something like this:

 $foo = 3;
 @bar = (
    'this',
    'that'
 );

However, sometimes a C<$VAR1> or C<$VAR2> will creep in there.  This happens
if pass in anything I<but> a named variable.  For example:

 warn Dumper( $bar[2] ); # $VAR1 = ... can't figure out the name



( run in 1.694 second using v1.01-cache-2.11-cpan-39bf76dae61 )