1

我已将我的问题简化为一个小例子。从包中导入/导出函数的工作方式发生了一些我不理解的事情。

此代码有效,我可以从 use-myPack.pl 调用 greet()。

# myPack.pm
package myPack;
require Exporter;
@ISA = qw(Exporter);
@EXPORT_OK = ('greet');

sub greet {
    printf("Hello!\n");
}

1;

# use-myPack.pl
use myPack qw(greet);
greet();

# Output
PS C:\Users\adam> perl .\use-myPack.pl
Hello!

但是,当我从父目录调用 use-myPack.pl 并使用::运算符确保它仍然可以使用 myPack 时,它找不到调用的函数greet()

# myPack.pm
package myPack;
require Exporter;
@ISA = qw(Exporter);
@EXPORT_OK = ('greet');

sub greet {
    printf("Hello!\n");
}

1;

# use-myPack.pl
use adam::myPack qw(greet);
greet();

# Output
PS C:\Users> perl .\adam\use-myPack.pl
Undefined subroutine &main::greet called at .\adam\use-myPack.pl line 2.

谁能帮助解释为什么我可以greet()在第一种情况下打电话,而不能在第二种情况下打电话?

4

2 回答 2

1

指令中使用的包名称use必须与模块package指令中使用的包名称匹配(因为您最终会这样做PACKAGE_NAME->import(IMPORT_LIST))。

use Foo::Bar;     with     package Foo::Bar;     = ok
use Bar;          with     package Foo::Bar;     = not ok
use Foo::Bar;     with     package Bar;          = not ok

最简单的选择是更改要使用的模块

package adam::myPack;

让您继续使用

use adam::myPack qw( greet );

否则,您需要切换到

use myPack qw( greet );

并通过使用更改库搜索路径 ( @INC)使 Perl 找到模块

use lib 'adam';

或者

use FindBin qw( $RealBin );
use lib "$RealBin/adam";

如果 cwd 与脚本目录不同,则前者有效,而后者则不然。


替代品use lib

如果您调用目录lib而不是adam,则可以使用

use mylib;  # Short for something similar to:
            #   use FindBin qw( $RealBin );
            #   use lib "$RealBin/lib", "$RealBin/../lib";

或者,如果您有一个为所有脚本安装模块的目录(例如),请在登录脚本中为其~/perl5/lib设置环境变量。PERL5LIB

export PERL5LIB=~/perl5/lib     # sh & bash syntax
于 2013-05-04T21:32:30.253 回答
1

这是一个关于包模块之间差异的迷你教程。


use My::Package 1.0 (qw'some options');
#                  ↑ no comma

实际上与以下内容相同:

BEGIN{
  # load the <module> if it isn't loaded already
  require My::Package;
  # or
  require 'My/Package.pm';



  # check the version of the <package>
  'My::Package'->VERSION(1.0); # compare against $My::Package::VERSION

  # do extra processing in the <package>
  'My::Package'->import(qw'some options');
}

注意只require处理了模块,其余语句都处理了同名的包。

我的/Package.pm:

package My::Package;
use strict;
use warnings;

our $VERSION = 1.0; # checked by UNIVERSAL::VERSION
# you can actually override VERSION. ( don't though )

# bad example of an import method
sub import{ # called by C<use>
  my( $package, $filename, $line ) = caller;
  print 'you called ', __PACKAGE__, " from $filename at line $line with options @_\n";

  # the following is similar to how Exporter::import works
  no strict 'refs';
  *{ $package.'::exported_sub' } = \&My::Package::Subs::exported_sub;
}

package My::Package::Subs; # <== look another package in the same module

sub exported_sub{...}

如果您use使用空列表调用,import则不会调用。

use My::Package ();
BEGIN{
  require 'My/Package.pm';
}

这样做的主要原因是确保模块在编译时加载,而不是代表调用做任何额外的事情。


当你这样做时:

require Exporter; # loads module named Exporter
@ISA = qw(Exporter); # inherit C<import> from Exporter.

import的任何方法调用import都将由Exporter处理。这包括任何use陈述。
当然,前提是您不通过定义自己的方法importAUTOLOAD方法来覆盖它。



作为旁白

::不是运算符(否则它将在perlop中)。相反,并被称为包分隔符。
::'

如果::是运算符,您将能够执行A :: B :: Cand A::(B::C),这是(当前)语法错误。

于 2013-05-06T21:13:17.047 回答