3

我不明白这里发生了什么:

use PAR { file => 'foo.par', fallback => 1 };

我认为这是一个匿名哈希。模块如何从use生产线使用它?你能解释一下吗?

编辑:我对 PAR 模块不感兴趣。我只是对幕后的工作方式感兴趣。我怎样才能像这样配置我的模块?

4

5 回答 5

7

更简单地说,这就是有趣的 hashref 语法所做的(使用perldoc -f use作为参考):

假设我们有这个基本模块(把它放在Foo.pm你的当前目录中):

package Foo;

use Data::Dumper;
sub import
{
    print "import was passed these arguments: ". Dumper(\@_);
}

1;

当我们调用时perl -I. -wle'use Foo { a => 1, b => 2}',代码Foo->import({a=>1, b=>2})被执行。所以这就是我们得到的输出:

import was passed these arguments: $VAR1 = [
          'Foo',
          {
            'a' => 1,
            'b' => 2
          }
        ];

基本上,这种语法让我们对Exporter施展魔法,但事实上你可以import()做任何你喜欢的事情(只要确保大量记录,以免造成混乱!)

于 2009-09-04T21:43:21.187 回答
7

当您use是一个模块时,您可以将参数列表传递给它。在您的示例中(似乎有错字,缺少右引号),传递了一个包含一个元素(哈希引用)的列表。

更普遍:

use Module LIST

变成这样:

BEGIN {
    require Module;
    Module->import( LIST );
}

BEGIN块确保所有的东西都发生在编译时。将require模块加载到内存中,如果它不存在的话。然后使用原始语句中传递的任何参数(as)调用模块的import()方法。LISTuse

为了让您自己的模块使用这样LIST的参数做某事,您的模块需要定义一个import()方法。许多模块不这样做。相反,它们import()Exporter类继承。有关更多详细信息,请参阅perldoc -f 使用

如果您的模块定义了自己的import()方法,您将需要自己将符号导出到客户端代码中,或者更常见的是export_to_level()使用Exporter. 此方法的第一个参数是一个正整数,指定调用堆栈中要将符号导出到的级别。最常见的值 1 表示将符号导出到当前包的上一级- 即,导出到正在使用您的模块的客户端代码。以下是您的import()方法需要执行的操作的概述。

sub import {
    my ($class, @args) = @_;

    # Do whatever you need to do with the LIST of arguments
    # supplied by the client code using your module.


    # Let Exporter do its normal work of exporting symbols
    # into the client code using your module.
    $class->export_to_level(1, @_);
}
于 2009-09-04T21:48:23.643 回答
2

是的,这是一个匿名哈希。它作为参数传递给 modulesimport方法。

于 2009-09-04T21:49:29.787 回答
0

PAR 是 CPAN 模块Perl Archive Toolkit。hashref 是传递给 PAR 的配置参数。

编码:

use PAR { file => 'foo.par, fallback => 1 };
use Foo::Bar;

表示Foo::Bar如果可用则使用,否则回退到使用存档“ foo.par”(可能包含 的存档版本Foo::Bar)。

于 2009-09-04T21:18:44.810 回答
0

直接回答您的问题:PAR 执行此操作(第 340 行)

# called on "use PAR"
sub import {
    my $class = shift;
    [...]
    my @args = @_;
    [...]
    # process args to use PAR 'foo.par', { opts }, ...;
    foreach my $par (@args) {
        if (ref($par) eq 'HASH') { # <---- This is what handle's your case!
            # we have been passed a hash reference
            _import_hash_ref($par);
        }
        elsif ($par =~ /[?*{}\[\]]/) {
           # implement globbing for PAR archives
           [...]
        }
        else {
            # ordinary string argument => file
            [...]
        }
    }

现在,不幸的是,一旦你深入了解那里真正发生的事情,你就会意识到你已经选择了 CPAN 上最复杂的模块之一作为学习的例子,所以我建议你看看关于模块代替。给你一个指导:当你“使用”一个模块并为 use 语句提供参数时,perl 将加载模块并使用参数列表调用它的“import”方法。

在您的示例中,只有一个参数:对哈希的引用。{key=>"value",key2=>"value2",...} 语法是匿名哈希的构造函数。这些都记录在perlref 手册页中,但在perlreftut 教程中以更友好的术语解释。

于 2009-09-04T22:25:37.350 回答