Perl关键字要求给出了奇怪的结果

时间:2012-03-20 18:46:57

标签: perl

我遇到了一个问题,我的程序无限循环。我缩小了问题的范围,结果发现关键字导致了这种情况。因此,为了理解这个问题,我写了一个简单的hello world程序,它具有确切的文件包含结构作为更大的程序。它有一个主文件 test.pl ,它从 test2.pm 调用helloWorld。 test2.pm从 test1.pm 调用相同的例程。

Test.pl

#!/usr/bin/perl
use test1;
use test2;
print "In test\n";
test2::helloWorld();

Test1.pm

#!/usr/bin/perl
package test1;
use test2;
require "test.pl";
@ISA = qw (Exporter);
@Export = qw(
    helloWorld
    );

sub helloWorld {
print "Hello world: Test1\n";
}

Test2.pm:

#!/usr/bin/perl
package test2;  
use test1;
@ISA = qw (Exporter);
@Export = qw(
    helloWorld
    );

sub helloWorld {
test1::helloWorld();
}

这是该程序的输出:

In test
Hello world: Test1
In test
Hello world: Test1

我希望了解为什么它会两次打印输出?如果我发表评论  从test1.pm #require“test.pl”,它只输出一次输出。

Test1.pm(需要注释掉的行)

#!/usr/bin/perl
    package test1;
    use test2;
    #require "test.pl";
    @ISA = qw (Exporter);
    @Export = qw(
         helloWorld
            );
    sub helloWorld {
        print "Hello world: Test1\n";
    }

这就是现在的输出:

In test
Hello world: Test1

我想如果我明白这一点,我就能解决我的真正问题。感谢您在这方面的任何帮助:)

2 个答案:

答案 0 :(得分:4)

执行perl脚本时,到目前为止通过requireuse加载的文件都保存在%INC哈希中,以防止代码执行多次,并且防止无限的相互递归。但是,您从其导入的某个模块导入主脚本,因此它将在导入过程中运行一次,并再次作为脚本运行。以下是加载和执行文件的顺序:

  1. test.pl运行并看到它需要加载test1.pm
    1. test1.pm已加载,它看到需要加载test2.pm
      1. test2.pm已加载,并且它看到需要加载test1.pm,但test1.pm已加载,因此会继续。
      2. test2::helloWorld已定义,test2.pm返回。
    2. 回到test1,它现在看到需要加载test.pl
      1. test.pl,我们尝试加载test1.pmtest2.pm,但它们已经通过require加载。
      2. 打印"在测试"并致电test2::helloWorld
    3. 返回test1.pm,定义test1::helloWorld
  2. 返回test.pl,打印"在测试"并致电test2::helloWorld

答案 1 :(得分:3)

你的代码中有很多错误,有些错误则不同。

  • 包名称应与.pm文件的名称相匹配,包括案例

由于您使用的是不区分大小写的文件系统(OS X或Windows),因此您可以轻松逃脱。 userequire记住他们是否已加载模块,但他们记住文件名,而不是模块名称。当你说use test1 Perl会寻找test1.pm时,却会加载Test1.pm。下次看到use test1时,它会看到它未加载test1.pm并再次加载......再次加载......再次加载。

  • 将函数导出的变量为@EXPORT而不是@Export

案例涉及变量名称。

  • 要求test.pl中的Test1.pmTest2.pm设置循环依赖。

这就是问题所在。 Perl在加载test.pl时(Test1.pm在编译时发生)尚未完成编译useTest1.pm编译然后被要求加载test.pl(运行时发生require)。然后test.pl的原始编译完成并运行其代码。

您有类似的潜在问题,因为Test1.pm使用Test2.pmTest2.pm使用Test1.pm

这令人困惑,有点像时间旅行。让我们简单一点:避免循环依赖

Test1.pm没有理由使用test.pl.通常,模块永远不应该加载程序。