我怎样才能包装要求和使用?

How can I wrap require and use?

假设我想包装 require 这样,

package MyModule;
use Data::Dumper;

会输出,

MyModule -> Data::Dumper
MyModule -> Data/Dumper.pm

对于所有包和所有 requires/use 语句。我该怎么做?

奇怪的要求需要奇怪的解决方案:使用源过滤器。

#!/usr/bin/perl
{   package Wrap::Use;
    use Filter::Simple sub {
        warn  while /use (.*?);/sg;                                  # stupid SO: /
    };
}

BEGIN { Wrap::Use->import }

use strict;
use warnings;
use Time::Piece;
BEGIN {
   unshift @INC, sub {
      printf "%s -> %s\n", ( caller() )[0], $_[1];
      return;
   };
}

请参阅 require's documentation 中以“您还可以将挂钩插入导入工具”开头的段落。

您不能将 require 内置函数作为子例程引用,例如 goto,但您可以从 CORE.

中调用它
use strict;
use warnings;
BEGIN {
  *CORE::GLOBAL::require = sub {
    printf "%s -> %s\n", [caller()]->[0], $_[0];
    CORE::require $_[0];
  }
};
use Data::Dumper;

您也可以考虑 Devel::TraceUse,它与上述类似,但更健壮且信息更丰富,并且可以轻松地从命令行调用。

您可以查看内部 Devel::TraceUse 以查看您正在尝试执行的操作的工作代码。但是,更改定义并不是一个好的计划,因为您不知道还有谁也更改了定义,并且会想知道为什么他们的东西停止工作。

您不需要(也不应该)覆盖 require。在 @INC 和 return false 末尾放置一个代码引用,这样看起来失败了,Perl 将继续 @INC:

中的下一件事
#!perl
use v5.10;

# 
BEGIN {
unshift @INC, sub {
    my( $package, $file ) = caller(0);
    say "$package -> $_[1]";
    return 0;
    };

}

use Data::Dumper;

say "Hello";

这输出:

main -> Data/Dumper.pm
Data::Dumper -> constant.pm
constant -> strict.pm
constant -> warnings/register.pm
warnings::register -> warnings.pm
Data::Dumper -> Carp.pm
Carp -> overloading.pm
Carp -> Exporter.pm
Data::Dumper -> XSLoader.pm
Data::Dumper -> bytes.pm
Hello