Perl, доступ к переменной по имени в другом скаляре - PullRequest
3 голосов
/ 09 июня 2011

Я почти уверен, что это работает с Perl, но я не знаю, как его кодировать.Я могу представить это с помощью eval, но это не то, что я ищу.

my $foo = 0;
my $varname = "foo";


$($varname) = 1;  # how to do this? 
# I want to access a scalar that name is in a other scalar
# so $foo should be 1 now.

Спасибо

Ответы [ 4 ]

8 голосов
/ 09 июня 2011

То, что вы пытаетесь сделать, называется символьной ссылкой , а синтаксис - ${$varname} (или просто $$varname для простых случаев).Но это почти всегда плохая идея , потому что это приводит к чрезвычайно трудным для диагностики ошибкам.Вот почему это запрещено use strict.

Вы можете сказать no strict 'refs', чтобы разрешить символические ссылки, но вы действительно , действительно , не должны't .

Двумя основными альтернативами символьным ссылкам являются хэши и жесткие ссылки .Трудно сказать, какой из них лучше подходит для вашей ситуации, потому что вы на самом деле не объяснили, что вы пытаетесь сделать.

3 голосов
/ 09 июня 2011

$$varname = 1 делает то, что вы хотите, но это запрещено, когда действует use strict;, и поэтому считается плохим стилем.

1 голос
/ 09 июня 2011

Perl имеет две отдельные, но в значительной степени совместимые переменные системы.

Переменные пакета, которые являются либо полностью квалифицированными именами $Some::Package::variable, либо лексическими именами, объявленными с our.Переменные пакета находятся в таблице символов, являются глобальными для всей программы, могут быть целью символической разыменования и могут иметь динамическую область видимости с local.

Лексическими переменными, объявленными с myсоставляют другую переменную систему.Эти переменные не живут в пакете или таблице символов (вместо этого они живут в лексической панели, которая прикреплена к области видимости).Эти переменные не являются глобальными, не могут иметь символическую ссылку и не могут иметь динамическую область видимости.Вот почему вы не можете использовать $$varname и ожидать, что он найдет лексическую переменную.

У вас есть несколько способов решить эту проблему:

  • use packageпеременные, либо полностью квалифицированные имена, либо объявленные с помощью our, строго запрещают использование и используют символические ссылки:

    our $x = 1;
    our $y = 'x';
    say $x;  # 1
    $$y = 5; # this line is an error if `use strict` is loaded
    say $x;  # 5
    
  • используют переменные пакета и обходят таблицу символов:

    $main::x = 1;
    my $y = 'x';
    
    ${$main::{$y}} = 5;  # ok with `use strict`
    say $main::x;  # 5
    
  • лучший способ - использовать хеш (что и делают два вышеупомянутых примера за кулисами, поскольку сама таблица символов является хешем)

    my %data = (x => 1);
    my $y = 'x';
    $data{$y} = 5;
    say $data{x};  # 5
    

Опасность символьных ссылок заключается в том, что зачастую слишком просто превратить вашу программу в код спагетти или перезаписать переменные, которые вы не собирались делать.Используя явный хеш, вы ограничиваете магию того, что вы делаете, четко определенной и ограниченной областью действия.Сам хеш может быть лексическим, что позволяет правильно собирать мусор ваших переменных.

0 голосов
/ 12 марта 2013

FAQ Perl отвечает на конкретный оригинальный вопрос:

http://learn.perl.org/faq/perlfaq7.html#How-can-I-use-a-variable-as-a-variable-name-

Содержит предупреждения, примеры и альтернативы в деталях.

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