如何将模块范围限制为子程序?

Zag*_*rax 4 perl scope

如果我运行下一个脚本:

use strict;
use warnings;

sub load {
    use File::Path qw (make_path);
}

load();
make_path('1/2/3/4');

exit 0;
Run Code Online (Sandbox Code Playgroud)

它完美地运作.我想将加载模块的范围限制在子例程中,这样我就不能使用在加载它的子例程之外的模块中声明的子例程.可能吗?

pma*_*olm 11

简短回答:不,这不太可能.

答案很长:加载File :: Path之后,您无法阻止代码调用,File::Path::make_path()但您可以通过短名称来限制可用范围.

use File::Path ();

sub load {
    local *make_path = \&File::Path::make_path;

    make_path('foo/bar/baz'); # This would work...
}

File::Path::make_path('bang/kapow'); # This would work too
make_path('xyxxy/plugh'); # But this would die
Run Code Online (Sandbox Code Playgroud)

但是通过使用local范围不是词法上限于语法代码块.它是动态范围的,意味着所有被调用的代码load()也将被make_path视为工作子例程.

我建议不要使用这种技术,因为它有点模糊,可能有一些难以解释的远处副作用.我发现它主要用于编写单元测试,它可以用于用模拟替换一些函数.

Perl开发人员正在讨论添加词汇subs作为语言的一部分.此功能应该允许您几乎完成您想要的操作而不会出现使用问题local.但是这仍然在进行中,甚至在perl的开发版本中也没有.

  • 顺便说一句,lexical subs正在为5.18开发! (3认同)