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 достаточно умен во время выполнения, чтобы знать, что это вызовы подпрограммы, и динамически искать их в таблице символов.

Другие вопросы по тегам