这些Perl使用线会发生什么?

时间:2009-09-04 21:17:03

标签: perl perl-module

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

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

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

编辑:我对PAR模块不感兴趣。我只是对窗帘后面的工作方式感兴趣。如何配置我的模块?

5 个答案:

答案 0 :(得分: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()做任何你喜欢的事情(只要务必记录下来以免引起混淆!)< / p>

答案 1 :(得分:7)

当你use一个模块时,你可以传递一个参数列表。在您的示例中(似乎有一个拼写错误,缺少结束引号),传递一个包含一个元素的列表(哈希引用)。

更一般地说:

use Module LIST

成为这个:

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

BEGIN块确保所有内容都在编译时发生。如果模块已经存在,require会将模块加载到内存中。然后使用原始import()语句中传递的任何参数(作为LIST)调用模块的use方法。

为了让您自己的模块使用这样的LIST参数执行某些操作,您的模块需要定义import()方法。许多模块不这样做;相反,他们从import()类继承Exporter。有关详细信息,请参阅perldoc -f use

如果您的模块定义了自己的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, @_);
}

答案 2 :(得分:2)

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

答案 3 :(得分:0)

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

代码:

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

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

答案 4 :(得分:0)

直接回答您的问题:PAR执行this (line 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上最复杂的模块之一作为一个例子来学习,所以我建议你看一下fine documentation on modules instead。为您提供指导:当您“使用”模块并为use语句提供参数时,perl将加载模块并使用参数列表调用其“import”方法。

在您的示例中,只有一个参数:对哈希的引用。 {key =&gt;“value”,key2 =&gt;“value2”,...}语法是匿名哈希的构造函数。这些内容记录在the perlref manual page中,但在the perlreftut tutorial中以更友好的术语进行了解释。