【问题标题】:What happens in these Perl use lines?这些 Perl 使用行会发生什么?
【发布时间】:2018-09-20 02:55:27
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: perl perl-module


    【解决方案1】:

    更简单地说,这就是有趣的 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() 做任何你喜欢的事情(只要确保大量记录,以免造成混乱!)

    【讨论】:

      【解决方案2】:

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

      更笼统地说:

      use Module LIST
      

      变成这样:

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

      BEGIN 块确保所有内容都在编译时发生。 require 将模块加载到内存中,如果它还没有的话。然后使用原始use 语句中传递的任何参数(如LIST)调用模块的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, @_);
      }
      

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          【解决方案4】:

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

          代码:

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

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

          【讨论】:

          • 哦。对不起。我不明白是什么让该语法起作用。我对 PAR 模块本身不感兴趣,只是作者如何使这成为可能。
          • 哈哈!在这种情况下,我刚刚为您的问题提供了真正的答案。 :)
          【解决方案5】:

          直接回答您的问题: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 中以更友好的方式解释。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-01-09
            • 1970-01-01
            • 2011-01-01
            • 2017-09-27
            • 1970-01-01
            • 2012-01-12
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多