解释这个巫术! (在Perl中,使用Moose和namespace :: autoclean)

时间:2013-02-04 18:00:08

标签: perl moose symbol-table mop

所以这些天我正在使用一个使用Perl和Moose的项目。我知道Moose是建立在MOP上的。我对MOP不太熟悉,我遇到了一些我不理解的东西,我可以使用理论解释。这是模块namespace::autoclean的文档:

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

所以,在我使用Moose之前,你在对象上调用方法的方式是:Perl解释器会在你的对象被祝福的包的符号表中查找该方法(如果不是发现,考虑@ISA继承等。它从包中调用导入函数的方式是:它在包的符号表中查找函数的名称。据我所知,到目前为止,这意味着相同的符号表,所以这种行为应该是不可能的。

我对来源的初步检查并不富有成效。从广义上讲,使用Moose,MOP和namespace :: autoclean时有什么不同,这种技巧变得可能吗?

ed。要特别清楚,如果我要用

替换use namespace::autoclean
CHECK { undef *Foo::imported_function }

然后文档中描述的Foo->bar;调用会崩溃,因为Foo->bar不知道在哪里找到imported_function

2 个答案:

答案 0 :(得分:3)

实际上非常简单。对于

some_sub()

some_sub在编译时解析。对于

$o->some_method()

some_method在运行时解析。它不能在编译时完成,因为它取决于$o

的值

答案 1 :(得分:1)

这里没有什么是非标准的。这条线

use Some::Package qw/imported_function/;

imported_function导入当前包,因此Foo::imported_functionSome::Package::imported_function的子例程相同。这假定Some::Package继承自Exporter以对符号表进行必要的操作。

调用是方法调用,因此Foo->barFoo::bar('Foo')相同。这里唯一特别的事情是,import的{​​{1}}函数所做的魔术在编译时间结束时被Exporter撤消。

我没有看过这个模块的代码,但是因为包的符号表只是一个哈希(称为 stash ,对于符号表哈希)在一个点上保持其状态并在之后恢复它将很容易。所以我猜想namespace::autoclean在加载时会获取符号表的快照,并在编译时结束时恢复状态。这可以方便地在CHECK block中完成,其行为类似于namespace::autoclean块,但在编译结束时和运行开始之前执行。