Perl'使用'语法如何工作?

时间:2010-11-10 18:28:09

标签: perl perl-module

示例代码:

  

m1.pm

my $a;
my $b;
sub init {
    $a = shift;
    $b = shift;
}

sub printab {
    print "a = -$a-\n";
    print "b = -$b-\n";
}

1;
  

m2.pm

my $a;
my $b;
sub init {
    $a = shift;
    $b = shift;
}

1;
  

test.pl

use strict;
use warnings;

use m1;
use m2;

init('hello', 'world');
printab();

执行命令

$ perl test.pl
a = --
b = --
$

如果init('hello', 'world')调用已映射到m2.pm并初始化变量($a$b),那么会发生什么。

这种说法很有道理,但我不明白为什么test.pl中没有这些值。

  • 我在这里尝试做的事情有根本错吗? 使用具有相同命名子例程和变量的两个模块的正确方法是什么?

  • Perl use的工作原理是什么?如果有人可以将它与C的#include指令进行对比,那将会有所帮助。

3 个答案:

答案 0 :(得分:13)

在Perl中,use关键字与以下内容完全等效:

use Mymodule;

#is the same as

BEGIN {
   require Mymodule;
   Mymodule->import();
}

因此,如果您没有在代码中定义导入例程(或继承自Exporter),那么您的模块不会将任何内容导入test.pl

正如Sinan捕获的那样,你没有在你的模块中声明一个包,所以它们默认为main包。在这种情况下,所有子例程都在main中,但是词法变量(用my声明)仅限于它们声明的文件。

因此,m1定义了词sub initsub printab所在的$a$b。但是当test.pl加载m2时,init例程会被新定义覆盖,而新定义不再围绕两个词汇关闭。所以它写入包变量$main::a$main::b而不是printab绑定的词汇。

如果您启用了警告(学习时总是应该这样做),您会收到有关子程序重新定义的警告。

您应该使用以下命令启动每个模块:

package Some::Package::Name;
use warnings;
use strict;

然后以:

结束每个模块
1;

这是因为当你use/require一个模块时,它需要在结尾返回一个真值,以便Perl知道它已正确加载。

答案 1 :(得分:8)

首先,请阅读perldoc perlmod

您不会在任一模块中声明命名空间,因此所有内容都位于main命名空间中。在package m1;m1.pmpackage m2;声明m2.pm

至少,您应该实现import方法(或继承Exporter提供的方法),以便使用模块的程序可以决定从哪里导入。

在我看来,你正在探索OO的边缘。

此外:

  • 避免使用$a$b作为变量名,因为很容易将它们与$a使用的包变量$bsort混淆}。

  • 不要使用小写模块名称:它们是为pragmata保留的。

最小的实现(所有在一个文件中以便于测试)如下所示:

package My::M1;

use strict; use warnings;

sub new { my $class = shift; bless { @_ } => $class }

sub a {
    my $self = shift;
    my ($v) = @_;
    $self->{a} = $v if @_;
    return $self->{a};
}

sub b {
    my $self = shift;
    my ($v) = @_;
    $self->{b} = $v if @_;
    return $self->{b};
}

package My::M2;

use strict; use warnings;
use base 'My::M1';

sub printtab {
    my $self = shift;
    for my $x (qw(a b)) {
        printf "%s = -%s-\n", $x, $self->$x;
    }
}

package main;

my $m = My::M2->new(a => 'hello', 'b' => 'world');
$m->printtab;

答案 2 :(得分:2)

printab()在文件m1.pm中定义,只能访问作用于该文件的$a$b变量。 $a中的变量$bm2.pm的范围限定为该文件,它们是不同的变量而不是$a$bm1.pm

init()设置m2.pm范围内的变量(因为这是定义&init函数的最后位置)所以它没有设置printab()将成为相同的变量试图打印。