Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to limit module scope to a subroutine?

Tags:

scope

perl

if I run the next script:

use strict;
use warnings;

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

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

exit 0;

It works perfectly. I would like to limit the scope of a loaded module to the subroutine so that I cannot use subroutines declared in the module outside the subroutine which loads it. Is it possible?

like image 920
Zagorax Avatar asked Dec 07 '22 11:12

Zagorax


2 Answers

Short answer: No, this is not really possible.

Long answer: After loading File::Path you can not prevent code from calling File::Path::make_path() but you can sort of limit the scope where it is availabel by the short name.

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

But by using localthe scope is not lexically restricted to the syntactical code block. It is dynamically scoped meaning that all code called by load() would also see make_path as a working subroutine.

I would recommend against using this technique as it is kind of obscure and can have some hard to explain side effects at a distance. I mostly find it useful for writing unit tests where it might be usable to replace some functions with mock ups.

The Perl developers are discussing adding lexical subs as part of the language. This feature should allow you to do nearly what you want without the problems of using local. But this is still work in progress and not even available in the development releases of perl.

like image 80
pmakholm Avatar answered Jan 03 '23 21:01

pmakholm


In short: you can't. Even 'worse', the use is executed compile time, so it doesn't make any difference that you put it in your sub (except for the cosmetic benefit).

like image 32
pavel Avatar answered Jan 03 '23 23:01

pavel