So these days I'm working with a project that uses Perl and Moose. I understand Moose is built on MOP. I'm not too familiar with MOP, and I've encountered something I don't understand, and I could use a theoretical explanation. Here is the module namespace::autoclean
's documentation:
SYNOPSIS
package Foo;
use namespace::autoclean;
use Some::Package qw/imported_function/;
sub bar { imported_function('stuff') }
# later on:
Foo->bar; # works
Foo->imported_function; # will fail. imported_function got cleaned after compilation
So, back before I ever used Moose, the way that you called a method on an object was: the Perl interpreter would look up that method in the symbol table of the package that your object was blessed into (then, if not found, consider @ISA
inheritance and the like). The way it called an imported function from within the package was: it looked up the name of the function in the symbol table of the package. As far as I've been aware to date, that means the same symbol table, either way, so this behavior should be impossible.
My initial inspection of the source was not productive. In broad terms, what is different when using Moose, MOP, and namespace::autoclean, that this sort of trickery becomes possible?
ed. To be especially clear, if I were to replace use namespace::autoclean
with
CHECK { undef *Foo::imported_function }
then the Foo->bar;
call described in the documentation would crash, because Foo->bar
doesn't know where to find imported_function
.
It's actually quite simple. For
some_sub()
some_sub
is resolved at compile time. For
$o->some_method()
some_method
is resolved at runtime. It cannot be done at compile-time since it depends on the value of $o
.