Почему я не могу использовать значение переменной Perl для доступа к имени лексической переменной? - PullRequest
6 голосов
/ 26 февраля 2010

Почему это печатает 42:

$answer = 42;
$variable = "answer";

print ${$variable} . "\n";

но это не так:

my $answer = 42;
my $variable = "answer";

print ${$variable} . "\n";

Ответы [ 4 ]

15 голосов
/ 26 февраля 2010

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

См. Отличную статью Как справиться со Scoping , чтобы узнать, как работают две отдельные системы переменных в Perl И посмотрите также превосходное Почему глупо использовать переменную с именем , почему это глупо. :)

6 голосов
/ 26 февраля 2010

В Perl есть две совершенно разные, но в значительной степени совместимые системы переменных, переменные пакета, как в первом примере, и лексические переменные, как во втором. Есть несколько вещей, которые каждый может сделать, но другой не может:

Переменные пакета - единственные, которые могут быть:

  1. локализовано (с local)
  2. используется в качестве цели для символической ссылки (причина, по которой второй пример OP не работает)
  3. используется как голые слова (подопределения, дескрипторы файлов)
  4. используется с typeglobs (потому что это то, что символ на самом деле находится под капотом)

Лексические переменные - единственные, которые могут быть закрыты (используются в лексическом закрытии).

Использование строгого режима поможет вам объявить переменные пакета с помощью our, что сделает разницу более ясной.

Есть несколько случаев, когда символические ссылки полезны в Perl, большинство из которых сосредоточено на манипулировании таблицей символов (например, написание собственного import в модуле, а не на использовании Exporter, модули обезьяноподготовки во время выполнения, различные другие мета программирование задач). Все это сложные темы.

Для других задач обычно есть лучший способ сделать это, например, с помощью хэша. Основное правило: всегда запускать под use warnings; use strict;, если только вы не знаете, что другого выхода нет, кроме как отключить часть прагмы (например, использовать no strict 'refs'; в как можно меньшем объеме).

5 голосов
/ 26 февраля 2010

Символьные ссылки работают только с переменными пакета. Таблица символов не отслеживает лексические переменные (в этом вся суть их лексичности:).

4 голосов
/ 26 февраля 2010

Проблема в том, что вы не можете использовать символическую ссылку для ссылки на лексическую переменную. В обоих примерах ${$variable} ищет $main::answer. Во-первых, $answer является глобальным пакетом и коротким для $main::answer, поэтому ссылка находит его. Во втором * $answer является лексической переменной и не существует ни в одном пакете, поэтому ссылка не может найти ее.

Подробнее в perlref под заголовком Символические ссылки .

...