Получить имя переменной в виде строки в Perl - PullRequest
9 голосов
/ 05 марта 2011

Я пытаюсь получить текстовое представление имени переменной.Например, это будет функция, которую я ищу:

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

Я хочу это, потому что я пытаюсь написать функцию отладки, которая рекурсивно выводит содержимое переданной переменной, я хочу, чтобы она вывелаимя переменной перед рукой, поэтому, если я вызову эту функцию отладки 100 раз подряд, не возникнет путаницы относительно того, какую переменную я смотрю в выводе.

Я слышал о Data :: Dumper и не являюсьпоклонник.Если кто-то может сказать мне, как, если возможно, получить строку с именем переменной, это было бы здорово.

Спасибо!

Ответы [ 3 ]

9 голосов
/ 05 марта 2011

Данные :: Дампер :: Простой

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

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

__END__

$abc
7 голосов
/ 05 марта 2011

Для этого вам нужно использовать модуль PadWalker , который позволяет вам проверять лексические площадки, которые хранят переменные.

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";
    }
}

и затем использовать его:

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

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

который печатает:

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

EDIT:

Вот та же функциональность, немного переработанная:

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";
    }
}
0 голосов
/ 05 марта 2011

Имена "my" (лексических) переменных стираются, поэтому вы не можете получить их имена. Имена переменных пакета доступны через запись таблицы символов (*var), как упоминалось в статье.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...