Perl 如何“使用”?语法工作?
示例代码:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在 Perl 中,
use
关键字与以下内容完全相同:因此,如果您没有在代码中定义导入例程(或从
Exporter
继承),那么您的模块没有将任何内容导入test.pl
正如 Sinan 所发现的那样,您没有在模块中声明包,因此它们默认为
main
包。在这种情况下,所有子例程都位于main
中,但词法变量(用my
声明)的作用域仅限于声明它们的文件。因此
m1
定义了词法$a
和$b
所在的sub init
和sub printab
范围。但是,当test.pl
加载m2
时,init
例程将被新定义覆盖,新定义不再围绕两个词法封闭。因此它正在写入包变量$main::a
和$main::b
而不是printab
绑定到的词法。如果您启用了警告(学习时总是应该这样做),您将会收到有关子例程重新定义的警告。
您应该以: 开始每个模块
,然后以: 结束每个模块,
这是因为当您
use/require
一个模块时,它需要在最后返回一个 true 值,以便 Perl 知道它已加载适当地。In Perl, the
use
keyword is exactly equivalent to the following:So if you are not defining an import routine in your code (or inheriting from
Exporter
), then your modules are not importing anything intotest.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 inmain
, but the lexical variables (declared withmy
) are only scoped to the file they are declared in.So
m1
definessub init
andsub printab
to which the lexicals$a
and$b
are in scope. But then whentest.pl
loadsm2
, theinit
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 whichprintab
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:
and then end each module with:
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.首先,请阅读 perldoc perlmod。
您没有在这两个模块中声明命名空间,因此所有内容都位于
main
命名空间中。在m1.pm
中声明package m1;
,在m2.pm
中声明package m2;
。至少,您应该实现一个
import
方法(或继承Exporter
提供的方法),以便使用模块的程序可以决定从哪里导入什么。在我看来,您似乎正在探索面向对象的边缘。
此外:
避免使用
$a
和$b
作为变量名,因为很容易将它们与包变量$a
和$b
由sort
使用。不要使用小写模块名称:它们是为 pragmata 保留的。
一个最小的实现(为了测试方便,全部在一个文件中)如下所示:
First, do read perldoc perlmod.
You do not declare a namespace in either module, so everything is in the
main
namespace. Declarepackage m1;
inm1.pm
andpackage m2;
inm2.pm
.At the very least, you should implement an
import
method (or inherit the oneExporter
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 bysort
.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:
printab()
在文件m1.pm
中定义,并且只能访问$a
和$b
作用域为该文件的变量。m2.pm
中的变量$a
和$b
的作用域为该文件,并且它们是不同的变量比m1.pm
中的$a
和$b
更重要。init()
设置范围在m2.pm
中的变量(因为这是定义&init
函数的最后一个位置),所以它不是设置printab()
将尝试打印的相同变量。printab()
is defined in the filem1.pm
and only has access to the$a
and$b
variables that are scoped to that file. The variables$a
and$b
inm2.pm
are scoped to that file, and they are different variables than the$a
and$b
inm1.pm
.init()
sets the variables scoped inm2.pm
(because that's the last place the&init
function was defined) so it is not setting the same variables thatprintab()
will be trying to print.