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

Laz*_*zer 0 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;
Run Code Online (Sandbox Code Playgroud)

m2.pm

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

1;
Run Code Online (Sandbox Code Playgroud)

test.pl

use strict;
use warnings;

use m1;
use m2;

init('hello', 'world');
printab();
Run Code Online (Sandbox Code Playgroud)

跑:

$ perl test.pl
a = --
b = --
$
Run Code Online (Sandbox Code Playgroud)

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

这种做法很有意义,但我不明白为什么这些价值观无法获得test.pl.

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

  • Perl究竟是如何use工作的?如果有人可以将它与C的#include指令进行对比,那将会有所帮助.

Eri*_*rom 13

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

use Mymodule;

#is the same as

BEGIN {
   require Mymodule;
   Mymodule->import();
}
Run Code Online (Sandbox Code Playgroud)

因此,如果您没有在代码中定义导入例程(或从中继承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;
Run Code Online (Sandbox Code Playgroud)

然后结束每个模块:

1;
Run Code Online (Sandbox Code Playgroud)

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


Sin*_*nür 8

首先,阅读perldoc perlmod.

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

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

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

进一步:

  • 避免使用$a$b作为变量名称,因为很容易将它们与包变量混淆$a$b使用sort.

  • 不要使用小写模块名称:它们是为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;
Run Code Online (Sandbox Code Playgroud)

  • @Lazer =>它不一定是,但按照惯例,它是. (3认同)