2009-09-04 28 views
3

我不明白这里发生了什么:这些Perl使用行会发生什么?

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

我认为这是一个匿名的哈希值。 use系列模块如何使用它?你能说出一些光明吗?

编辑:我对PAR模块不感兴趣。我只是对如何在幕后工作感兴趣。我该如何配置我的模块?

回答

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()做任何你喜欢的(只是一定要记录巨资,以不导致混淆!)

0

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

代码:

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

意味着使用Foo::Bar如果可用,否则退回到使用存档“foo.par”(这大概持有Foo::Bar存档版本)。

+0

哦。抱歉。我不明白是什么让语法起作用。我对PAR模块本身并不感兴趣,只是作者如何做到这一点。 – Geo 2009-09-04 21:25:31

+0

阿哈!在那种情况下,我刚刚提供了你的问题的真实答案。 :) – Ether 2009-09-04 21:43:59

7

当你模块use,你可以传递一个参数列表给它。在你的例子中(似乎有一个错字,缺少一个结尾引用),一个包含一个元素(一个散列引用)的列表被传递。

更一般地:

use Module LIST 

变为这样的:

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

BEGIN块确保所有的事情发生在编译时。 require将模块加载到内存中,如果它尚未存在。然后在原始use语句中调用模块的import()方法,并传递任何参数(如LIST)。

为了让您自己的模块能够处理这样的参数,您的模块需要定义一个import()方法。许多模块不这样做;相反,他们从Exporter类继承import()。有关更多详情,请参阅perldoc -f use

如果你的模块定义了自己的import()方法,你要么需要符号导出到客户端代码自己,或者更常见的是,使用由Exporter提供的export_to_level()方法。此方法的第一个参数是一个正整数,用于指定要将符号导出到的调用堆栈中的级别。最常见的值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

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

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 =>“value”,key2 =>“value2”,...}语法是匿名哈希的构造函数。这些记录在the perlref manual page中,但在the perlreftut tutorial中以更友好的术语解释。