Perl: прототип в анонимной подпрограмме
В настоящее время я изучаю систему перглсов и пространств имен Perls. Поэтому я написал модуль, который принимает два аргумента: значение и имя константы и экспортирует константу для вызывающей стороны. Переменная $package равна caller[2].
*{"$package::$name"} = sub () { return $value; };
Приведенный выше код выполняет работу по экспорту анонимной подпрограммы в символьную структуру вызывающих абонентов. Поскольку моя цель состоит в том, чтобы создать мою собственную постоянную реализацию, подпрограмма имеет пустой прототип, что означает, что она предназначена только для чтения.
Но это моя проблема: прототип не работает. Так
print &TestConst; #works well
print TestConst(); #works well
print TestConst; #Name "main::TestConst" used only once: possible typo at testscript.pl line 7.
Что-то не так в моих мыслях? Есть ли другой способ сделать это?
1 ответ
Вы можете определить все символы, которые вы хотите во время выполнения, но прототипы будут влиять только на код, скомпилированный впоследствии, так как прототипы влияют на то, как анализируются и компилируются вызовы подпрограммы. Например:
use strict;
use warnings;
package Foo;
BEGIN {
*Foo::bar = sub () { 42 };
}
*Foo::baz = sub () { 43 };
my $bar = bar;
my $baz = baz;
print "bar = [$bar], baz = [$baz]\n";
Если мы запустим это, он умрет с:
Базовое слово "baz" не допускается, когда в строчке 13 tprot.pl используются "строгие сабы"
Это ошибка времени компиляции, вызванная strict
: компилятор увидел символ baz
и не знал, что это было, потому что typeglob *Foo::baz
не изменяется до времени выполнения. Но bar
работал нормально, потому что это было определено в BEGIN
блок, который выполняется сразу во время компиляции.
Итак, поскольку голые слова неоднозначны, Perl должен знать во время компиляции, является ли он сабом или чем-то еще. Таким образом, вы можете установить их во время import
(который выполняется в неявном BEGIN
блок) но не во время выполнения.
Кроме того, прототипы влияют на семантику компиляции; постоянная подпрограмма (например, сделанные constant.pm
) оптимизируется прочь Другие прототипы приводят к тому, что синтаксический анализатор меняет свое поведение (например, подпрограммы, которые могут принимать блоки кода). Компилятор должен знать обо всем этом, прежде чем вызовы подпрограммы фактически встретятся в коде, чтобы их можно было правильно проанализировать. Код запускается после того, как все уже проанализировано.
Вызов подпрограммы с явными паренами или с амперсандом не имеет этого ограничения, потому что Perl достаточно умен во время выполнения, чтобы знать, что это вызовы подпрограммы, и динамически искать их в таблице символов.