13

I am trying to get a text representation of a variable's name. For instance, this would be the function I am looking for:

$abc = '123';
$var_name = &get_var_name($abc); #returns '$abc'

I want this because I am trying to write a debug function that recursively outputs the contents of a passed variable. I want it to output the variable's name before hand so if I call this debug function 100 times in succession, there will be no confusion as to which variable I am looking at in the output.

I have heard of Data::Dumper and am not a fan. If someone can tell me how to if it's possible get a string of a variable's name, that would be great.

4
  • 4
    Why not just use Perl's built-in debugging tools instead of reinventing the wheel? Commented Mar 4, 2011 at 22:17
  • 1
    I suspect that Devel::StackTrace would be a better solution to your problem then hunting down variable names. Commented Mar 4, 2011 at 22:18
  • 1
    Why aren't you a fan of Data::Dumper? If we know exactly what your requirements are and why Data::Dumper doesn't satisfy them, it will be easier to answer your question. Without further information, all I can do is recommend Data::Dumper because it's what I use for this. Commented Mar 4, 2011 at 22:19
  • 2
    I don't actually see what help Data::Dumper would be in this case. Commented Mar 4, 2011 at 22:28

3 Answers 3

13

Data::Dumper::Simple

use warnings;
use strict;
use Data::Dumper::Simple;

my $abc = '123';
my ($var_name) = split /=/, Dumper($abc);
print $var_name, "\n";

__END__

$abc
Sign up to request clarification or add additional context in comments.

Comments

9

To do this, you need to use the module PadWalker, which lets you inspect the lexical pads that store variables.

use PadWalker qw/peek_my peek_our/;

sub debug {
    my $my     = peek_my 1;
    my $our    = peek_our 1;
    my $caller = caller() . '::';
    my $stash  = do {
        no strict 'refs';
        \%$caller
    };
    my %lookup;
    for my $pad ($my, $our) {
        $lookup{$$pad{$_}} ||= $_ for keys %$pad;
    }
    for my $name (keys %$stash) {
        if (ref \$$stash{$name} eq 'GLOB') {
            for (['$' => 'SCALAR'],
                 ['@' => 'ARRAY'],
                 ['%' => 'HASH'],
                 ['&' => 'CODE']) {
                if (my $ref = *{$$stash{$name}}{$$_[1]}) {
                    $lookup{$ref} ||= $$_[0] . $caller . $name
                }
            }
        }
    }
    for (@_) {
       my $name = $lookup{\$_} || 'name not found';
       print "$name: $_\n";
    }
}

and then to use it:

my $x = 5;
our $y = 10;
$main::z = 15;

debug $x, $y, $main::z;

which prints:

$x: 5
$y: 10
$main::z: 15

EDIT:

Here is the same functionality, refactored a bit:

use PadWalker qw/peek_my peek_our/;

sub get_name_my {
    my $pad = peek_my($_[0] + 1);
    for (keys %$pad) {
        return $_ if $$pad{$_} == \$_[1]
    }
}
sub get_name_our {
    my $pad = peek_our($_[0] + 1);
    for (keys %$pad) {
        return $_ if $$pad{$_} == \$_[1]
    }
}
sub get_name_stash {
    my $caller = caller($_[0]) . '::';
    my $stash = do {
        no strict 'refs';
        \%$caller
    };
    my %lookup;
    for my $name (keys %$stash) {
        if (ref \$$stash{$name} eq 'GLOB') {
            for (['$' => 'SCALAR'],
                 ['@' => 'ARRAY'],
                 ['%' => 'HASH'],
                 ['&' => 'CODE']) {
                if (my $ref = *{$$stash{$name}}{$$_[1]}) {
                    $lookup{$ref} ||= $$_[0] . $caller . $name
                }
            }
        }
    }
    $lookup{\$_[1]}
}
sub get_name {
    unshift @_, @_ == 2 ? 1 + shift : 1;
    &get_name_my  or
    &get_name_our or
    &get_name_stash
}

sub debug {
    for (@_) {
       my $name = get_name(1, $_) || 'name not found';
       print "$name: $_\n";
    }
}

Comments

-4

"my" (lexical) variables' names are erased, so you can't get their names. Package variables' names are available via the symbol table entry (*var), as mentioned elsearticle.

1 Comment

That was definitely not the question. And there IS a way to get names of lexical and global variables used in a call. Look at the other answers. Look at Devel::Caller and PadWalker.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.