I am currently learning about Perls system of typeglobs and namespaces. So I wrote a module that takes two arguments the value and the name of a constant and exports the constant to the caller. The $package variable is equal to caller[2].
*{"$package::$name"} = sub () { return $value; };
This code above does the job of exporting a anonymous subroutine into the callers symboltable. Because my goal is to build my own constant-implementation the subroutine has a empty prototype which means its a read-only subroutine.
But this is my problem: the prototype does not work. So
print &TestConst; #works well
print TestConst(); #works well
print TestConst; #Name "main::TestConst" used only once: possible typo at testscript.pl line 7.
Is there something wrong in my thoughts? Is there another way of doing it?
You can define all the symbols you want during runtime, but prototypes will only affect code compiled afterwards since prototypes affect how calls to the sub are parsed and compiled. For example:
If we run this, it dies with:
That's a compile-time error caused by
strict
: the compiler saw the symbolbaz
and didn't know what it was, because the typeglob*Foo::baz
does not get altered until runtime. Butbar
worked fine because it was defined in aBEGIN
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 implicitBEGIN
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.