2

所以这些天我正在处理一个使用 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 时,这种诡计变得可能有什么不同?

编。要特别清楚,如果我要替换use namespace::autoclean

CHECK { undef *Foo::imported_function }

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

4

2 回答 2

3

其实很简单。为了

some_sub()

some_sub在编译时解决。为了

$o->some_method()

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

于 2013-02-04T18:59:07.777 回答
1

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

use Some::Package qw/imported_function/;

导入imported_function到当前包中,因此Foo::imported_functionSome::Package::imported_function. 假设Some::Package继承自Exporter对符号表进行必要的操作。

调用是方法调用,因此Foo->barFoo::bar('Foo'). import这里唯一特别的是,函数 from已经完成的魔法Exporter在编译时间结束时 by 被撤消了namespace::autoclean

我没有看过这个模块的代码,但是由于包的符号表只是一个散列(称为stash,用于符号表散列),因此很容易在某一时刻保留其状态并在之后恢复它。所以我猜想namespace::autoclean在加载符号表时拍摄它的快照,并在编译时间结束时恢复该状态。这可以方便地在一个CHECK中完成,该块的行为类似于一个BEGIN块,但在编译结束和运行开始之前执行。

于 2013-02-04T18:29:03.497 回答