Perl 如何“使用”?语法工作?

发布于 2024-10-01 06:06:25 字数 963 浏览 5 评论 0原文

示例代码:

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 指令进行对比,将会有所帮助。

Sample code:

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();

Run:

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

What happens is that the init('hello', 'world') call is mapped to m2.pm and initializes the variables ($a and $b) there.

This kind of makes sense, but what I do not understand is why those values are not available in test.pl.

  • Is there something fundamentally wrong that I am trying to do here? What is the correct way to use two modules with same named subroutines and variables?

  • How exactly does a Perl use work? It would help if someone could contrast it with C's #include directive.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

云雾 2024-10-08 06:06:25

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

use Mymodule;

#is the same as

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

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

正如 Sinan 所发现的那样,您没有在模块中声明包,因此它们默认为 main 包。在这种情况下,所有子例程都位于 main 中,但词法变量(用 my 声明)的作用域仅限于声明它们的文件。

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

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

您应该以: 开始每个模块

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

,然后以: 结束每个模块,

1;

这是因为当您use/require 一个模块时,它需要在最后返回一个 true 值,以便 Perl 知道它已加载适当地。

In Perl, the use keyword is exactly equivalent to the following:

use Mymodule;

#is the same as

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

So if you are not defining an import routine in your code (or inheriting from Exporter), then your modules are not importing anything into test.pl

As Sinan caught, you are not declaring a package in your modules, so they are defaulting to the main package. In that case, all of your subroutines are in main, but the lexical variables (declared with my) are only scoped to the file they are declared in.

So m1 defines sub init and sub printab to which the lexicals $a and $b are in scope. But then when test.pl loads m2, the init routine is overwritten with the new definition, which is not closed around the two lexicals anymore. So it is writing to the package variables $main::a and $main::b instead of the lexicals which printab is bound to.

If you had warnings enabled (which you always should when learning), you would have been warned about the subroutine redefinition.

You should start each of your modules with:

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

and then end each module with:

1;

This is because when you use/require a module, it needs to return a true value at the end so that Perl knows it loaded properly.

不离久伴 2024-10-08 06:06:25

首先,请阅读 perldoc perlmod

您没有在这两个模块中声明命名空间,因此所有内容都位于 main 命名空间中。在 m1.pm 中声明 package m1;,在 m2.pm 中声明 package m2;

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

在我看来,您似乎正在探索面向对象的边缘。

此外:

  • 避免使用 $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;

First, do read perldoc perlmod.

You do not declare a namespace in either module, so everything is in the main namespace. Declare package m1; in m1.pm and package m2; in m2.pm.

At the very least, you should implement an import method (or inherit the one Exporter provides) so that programs that use modules can decide what to import from where.

It also seems to me that you are exploring around the edges of OO.

Further:

  • Avoid using $a and $b as variable names because it is easy to confuse them with the package variables $a and $b used by sort.

  • Don't use lower case module names: They are reserved for pragmata.

A minimal implementation (all in one file for testing convenience) looks like this:

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;
简单爱 2024-10-08 06:06:25

printab() 在文件 m1.pm 中定义,并且只能访问 $a$b作用域为该文件的变量。 m2.pm 中的变量 $a$b 的作用域为该文件,并且它们是不同的变量m1.pm 中的 $a$b 更重要。

init() 设置范围在 m2.pm 中的变量(因为这是定义 &init 函数的最后一个位置),所以它不是设置 printab() 将尝试打印的相同变量。

printab() is defined in the file m1.pm and only has access to the $a and $b variables that are scoped to that file. The variables $a and $b in m2.pm are scoped to that file, and they are different variables than the $a and $b in m1.pm.

init() sets the variables scoped in m2.pm (because that's the last place the &init function was defined) so it is not setting the same variables that printab() will be trying to print.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文