您可以在运行时定义您想要的所有符号,但原型只会影响之后编译的代码,因为原型会影响对子调用的解析和编译方式。例如:
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";
If we run this, it dies with:
Bareword "baz" not allowed while "strict subs" in use at tprot.pl line
13.
That's a compile-time error caused by strict
: the compiler saw the symbol baz
and didn't know what it was, because the typeglob *Foo::baz
does not get altered until runtime. But bar
worked fine because it was defined in a BEGIN
block, which executes immediately during compilation.
IOW, because barewords are ambiguous, Perl needs to know at compile-time whether it's a sub or something else. So you can install these during import
(which executes in an implicit BEGIN
block) but not at runtime.
Additionally, prototypes affect compilation semantics; a constant subroutine (like those made by constant.pm
) gets optimized away. Other prototypes cause the parser to change its behavior (e.g. subs which can take code blocks.) The compiler has to know about all this stuff before calls to the sub are actually encountered in the code, so they can be parsed correctly. The code runs after everything is already parsed.
Calling a sub with explicit parens or with an ampersand does not have this restriction because Perl is smart enough at runtime to know that these are subroutine calls, and to look them up dynamically in the symbol table.