在 Perl 中,如何访问另一个包中定义的标量?
我似乎被困在尝试访问另一个包中定义的标量,并将示例缩小为一个简单的测试用例,我可以在其中重现问题。 我希望能够使用我们的机制访问对包“Example”中定义的列表的引用,但是,Dumper 显示该变量在 example.pl 中始终未定义:
Example.pm如下所示:
#!/usr/bin/perl -w
use strict;
use warnings;
use diagnostics;
package Example;
use Data::Dumper;
my $exported_array = [ 'one', 'two', 'three' ];
print Dumper $exported_array;
1;
使用此包的代码如下所示:
#!/usr/bin/perl -w
use strict;
use warnings;
use diagnostics;
use Data::Dumper;
use lib '.';
use Example;
{ package Example;
use Data::Dumper;
our $exported_array;
print Dumper $exported_array;
}
exit 0;
运行此代码后,第一个 Dumper 运行,一切看起来正常,之后,第二个 Dumper example.pl 运行,然后引用未定义:
$VAR1 = [
'one',
'two',
'three'
];
$VAR1 = undef;
I seem to be stuck trying to access a scalar which is defined in another package, and have narrowed down an example to a simple test case where I can reproduce the issue.
What I wish to be able to do it access a reference to a list which is in defined within the package 'Example', using the our mechanism, however, Dumper is showing that the variable is always undefined within example.pl:
Example.pm looks like the following:
#!/usr/bin/perl -w
use strict;
use warnings;
use diagnostics;
package Example;
use Data::Dumper;
my $exported_array = [ 'one', 'two', 'three' ];
print Dumper $exported_array;
1;
And the code which uses this package looks like this:
#!/usr/bin/perl -w
use strict;
use warnings;
use diagnostics;
use Data::Dumper;
use lib '.';
use Example;
{ package Example;
use Data::Dumper;
our $exported_array;
print Dumper $exported_array;
}
exit 0;
Upon running this code, the first Dumper runs and things look normal, after this, the second Dumper, example.pl runs and the reference is then undefined:
$VAR1 = [
'one',
'two',
'three'
];
$VAR1 = undef;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
my
声明不会创建包级变量,也不会在任何命名空间的符号表中输入任何内容。要执行您想要执行的操作,您必须将第一个文件中的声明更改为
您可以在另一个文件中访问它,如下所示
A
my
declaration does not create a package level variable and does not enter anything onto the symbol table for any namespace.To do what you look like you are trying to do, you will have to change the declaration in the first file to
You can then access it in another file as
即使
$exported_array
未在Example
包中按词法限定范围,Example
的$exported_array
和 main 的$exported_array
是两个不同的东西。更改您给出的示例的最简单方法是 1. 在Example
声明中将my
更改为our
并显式限定变量名称。否则,您需要将
Example
设为Exporter
。 (或者只是编写一个Example::import
例程 - 但我不会介绍这一点。)在脚本中:
但是,因为您实际上可以导出数组(不仅仅是参考文献),我会这样做:
Even if
$exported_array
weren't lexically scoped in theExample
package,Example
's$exported_array
and main's$exported_array
are two different things. The easiest way to change the example you've given is to 1. changemy
toour
in theExample
declaration and explicitly qualify the variable name.Otherwise, you need to make
Example
anExporter
. (Or just write anExample::import
routine--but I' not going to cover that.)And in the script:
However, as you can actually export arrays (not just refs), I would make that:
当您使用
my
运算符时,您将按词法将变量名称的作用域限定为您所在的作用域或文件。如果您希望某些内容作为合格的包数组可见,则需要像在驱动程序代码中一样使用
our
。我相信您还需要在 .pm 文件中声明一些特殊的导出器变量,但从好的方面来说,您不需要在驱动程序文件中声明our $exported_array;
。When you use the
my
operator, you are lexically scoping the variable name to either the scope you're in or to the file.If you want something to be visible as a qualified package array, you need to use
our
like you do in the driver code. I believe you also need to declare a few special exporter variables in the .pm file, but on the plus side you won't need to declareour $exported_array;
in the driver file.对于较小的项目来说,使用 Exporter 没问题,但如果您有大量处理模块内部数据的代码,事情可能会变得……混乱。面向对象对于这种类型的事情要友好得多。
为什么不构造一个方法来获取这些数据呢?事实上,为什么不直接使用 Moose 呢?
在您的Example.pm中,只需加载Moose - 这会免费为您提供一个构造函数和析构函数,以及一个用于获取值的子例程和默认情况下打开严格等。由于 Class:MOP(驼鹿角下的引擎)初始化属性的方式,数组引用的声明方式必须略有不同 - 您必须将其包装在代码引用(又名 sub {})中。您还可以在调用包的脚本中使用 Data::Dumper,而不是包本身。
example.pm
然后从脚本中调用它:
example.pl
我在上面的 example.pl 脚本中非常明确地取消引用...通过直接将其取消引用到数组中可以更加简洁:
我认为很多 如果有更多简单的例子来展示如何完成简单的事情,更多的 Perl 程序员会接受 Moose。
官方驼鹿手册非常好,但它是确实是为那些已经熟悉 OOP 的人编写的。
Using Exporter is fine for smaller projects, but if you have lots of code handling data that is internal to a module, things can get ... messy. Object-orientation is a lot friendlier for this type of thing.
Why not construct a method to fetch this data? In fact, why not just use Moose?
In your Example.pm, just load Moose - this gives you a constructor and destructor for free, as well as a subroutine to fetch values and turns on strict, etc by default. Array references have to be declared a little differently, due to how Class:MOP (The engine under the antlers of Moose) initializes attributes - you have to wrap it in a code reference (aka sub {}). You would also use Data::Dumper in the script which calls the package, instead of the package itself.
Example.pm
Then call this from a script:
example.pl
I made the dereferencing really explicit in the example.pl script above... it can be much more terse by dereferencing it directly into the array:
I think a lot more Perl programmers would embrace Moose if there were more simple examples that show how to get simple things done.
The Official Moose Manual is excellent, but it was really written for those who are already familiar with OOP.