7

从我读过的关于使用 Perl 模块的所有内容来看,基本用法是:

  • 带有.pm扩展名的模块文件,其中包括语句package <name>,其中<name>是不带扩展名的模块的文件名。
  • 使用模块的代码文件包含语句use <name>;

我正在编写的应用程序有一个主要的代码脚本,它使用了大约 5 个模块。我忘记package <name>在模块中包含该语句,但我的代码仍然可以正常运行该use <name>语句。我开始收到Undefined subroutine其中一个模块的错误,因此我将 package 语句添加到每个模块中。现在这些模块的其余部分停止工作。是什么赋予了?

例子:

主应用程序.pl

#!/usr/bin/perl
use UtyDate;
my $rowDate = CurrentDate("YYYYMMDD");

UtyDate.pm

#!/usr/bin/perl
package UtyDate;
sub CurrentDate
{
    #logic
}
return 1;

当我运行上面的代码时,我得到了错误Undefined subroutine &main::CurrentDate called at...。但是,如果我package UtyDate;从 UtyDate.pm 中删除该行,则不会出现错误。这种情况存在于我的几个但不是所有模块中。

显然还有很多我没有展示的代码,但我很困惑我没有展示的任何代码如何影响我在这里展示的包/使用结构。

4

4 回答 4

10

使用模块时,模块中的代码在编译时运行。然后在模块的包名上调用 import。所以,use Foo;是一样的BEGIN { require Foo; Foo->import; }

您的代码在没有声明的情况下工作,因为所有代码都在主应用程序代码使用package的 package 下执行。main

当您添加package声明时它停止工作,因为您定义的子例程不再定义在 中main,而是在UtyDate.

您可以使用完全限定名称访问子例程,也可以在模块UtyDate::CurrentDate();中将子例程导入当前名称空间use

UtyDate.pm

package UtyDate;
use strict;
use warnings; 

use Exporter 'import';

# Export these symbols by default.  Should be empty!    
our @EXPORT = ();

# List of symbols to export.  Put whatever you want available here.
our @EXPORT_OK = qw( CurrentDate  AnotherSub ThisOneToo );

sub CurrentDate {
    return 'blah';
}

sub AnotherSub { return 'foo'; }

主程序:

#!/usr/bin/perl
use strict;
use warnings; 

use UtyDate 'CurrentDate';

# CurrentDate is imported and usable.    
print CurrentDate(), " CurrentDate worked\n";

# AnotherSub is not
eval {  AnotherSub() } or print "AnotherSub didn't work: $@\n";

# But you can still access it by its fully qualified name
print UtyDate::AnotherSub(), " UtyDate::AnotherSub works though\n";

有关更多信息,请参阅导出器文档。

于 2010-06-04T22:04:14.793 回答
3

您缺少导出器 perl 标头代码。您需要在 pm 文件顶部的 package 语句下方添加如下内容:

package UtyDate;
BEGIN {
  use Exporter ();
  use vars qw($VERSION @ISA @EXPORT);
  $VERSION = "1.0.0";
  @ISA = qw(Exporter);
  @EXPORT = qw( &CurrentDate );
}

请参阅此链接: http: //perldoc.perl.org/Exporter.html#DESCRIPTION

于 2010-06-04T21:05:31.260 回答
1

除了格雷的建议,您可以这样做:

use UtyDate;
UtyDate::CurrentDate(...);
于 2010-06-04T21:09:09.133 回答
0

正如 Gray 指出的那样,除了使用导出器之外,您还可以(UGLY,但有效)还可以使用模块名称调用函数 ..

您的功能/程序不起作用,因为它们现在位于不同的命名空间中(由模块名称定义)

use UtyDate;

UtyDate::CurrentDate(  )
于 2010-06-04T21:09:46.650 回答