3

怀疑perl基础use

它有点类似于我的另一个问题Perl:两个包在同一个文件中......

考虑一个 perl 脚本:

脚本.pl

use INCLUDES;

包括.pm

package INCLUDES;
use Exporter;

############# MY DOUBT STARTS HERE ###############
use Module1;
use Module2;
##################################################

our @ISA = qw(Exporter);
our @EXPORT = qw();

sub import {

  print 'INCLUDES imported to ' . caller . "\n";

}

模块1.pm

package Module1;

use strict;
use Exporter;
use INCLUDES;    #####=> INCLUDES.pm 'use'd

our @ISA = qw(Exporter);
our @EXPORT = qw();

1;

模块2.pm

package Module2;

use strict;
use Exporter;
use INCLUDES;  #####=> INCLUDES.pm 'use'd

our @ISA = qw(Exporter);
our @EXPORT = ();

1;

输出

D:\Do_analysis>Script.pl
INCLUDES imported to main

根据 perl 文档,use INCLUDES;在 Module1 & Module2 => BEGIN {require 'INCLUDES.pm'; 'INCLUDES'->import();}中。所以,import()应该在 Module1.pm , Module2.pm 中调用。

我希望输出如下所示,

预期输出??

D:\Do_analysis>Script.pl
INCLUDES imported to main
INCLUDES imported to Module1
INCLUDES imported to Module2

但是为什么执行不及预期呢?

更新

这就是我想要通过拥有 INCLUDES.pm 文件来实现的目标。

模块库

请注意:PACKAGE2可能想要访问 PACKAGE3、PACKAGE4 等。我不想单独访问use里面的所有模块PACKAGE2,而是想在所有其他模块中创建一个库INCLUDES和它。use

这种方法有效吗?还是值得推荐的?

我很欣赏有关如何实现这一目标的任何想法。谢谢!

4

2 回答 2

9

如果你要搬家

use Module1;
use Module2;

下面sub import { ... },你会得到预期的行为。


问题是你Module1.pm在编译器甚至到达之前sub import执行INCLUDES.pm

什么Module1.pm时候use INCLUDES;,Perl 会说“哦,它已经加载了”(对 的响应require)和“哦,它没有import”(对 的响应import),因为INCLUDES.pm创建的那部分import还没有被编译。对Module2.pm.

一般来说,如果你有一个相互包含的模块(直接或以其他方式),那么你做错了(在设计方面),你最终将不得不处理这些问题。您可能会发现Mini-Tutorial: Mutual Use of Exporting Modules在处理这些问题时很有用。

于 2013-07-19T01:47:48.383 回答
3

您的模块之间存在循环依赖关系。mainuses INCLUDES, INCLUDESuses Module1, and Module1uses INCLUDES(Module2在这里基本上是无关紧要的,除了作用相同Module1)。如果 perl 做了幼稚的事情,这将导致无限循环(或至少堆栈溢出),因为每次 perl 尝试编译INCLUDES它都会导致编译Module1,而每次 perl 尝试编译Module1它都会导致编译的INCLUDES

由于我们不希望这种情况发生,perl 必须做一些不同的事情。相反,它的作用是忽略任何编译已编译模块或已在编译过程中的模块的请求。所以事件的流程是:

  1. Perl 开始编译script.pl并进入包main
  2. Perl 看到use INCLUDES;、加载INCLUDES.pm并开始编译它。
  3. 在这一行package INCLUDES;,perl 进入了包INCLUDES
  4. Perl 看到use Module1;、加载Module1.pm并开始编译它。
  5. 在这一行package Module1,perl 进入了包Module1
  6. Perl 看到use INCLUDES;,意识到它已经在 compile 的过程中INCLUDES.pm,并且不会尝试再次编译它。
  7. 由于use INCLUDES;perl 尝试调用INCLUDES->import,但尚未定义导入方法(我们INCLUDES在第 4 步暂停编译以开始编译Module1)。
  8. 编译Module1完成,我们回到INCLUDES.
  9. PerlModule1->importINCLUDES.
  10. 编译INCLUDES完成,包括use Module2和 的定义sub import。Perl 回到main.
  11. INCLUDES->import被调用main并打印您的消息。
  12. 编译script.pl完成。
  13. script.pl运行时无事可做,perl 退出。
于 2013-07-19T01:50:19.453 回答