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

时间:2012-09-27 13:30:12

标签: perl scope

如果我运行下一个脚本:

use strict;
use warnings;

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

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

exit 0;

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

2 个答案:

答案 0 :(得分: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

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

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

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

答案 1 :(得分:4)

简而言之:你做不到。即使是“更糟糕”,use也会在编译时执行,因此将它放在您的sub中没有任何区别(除了美容效果)。