Lexically importing useful functions in a big script
Sometimes I need a useful utility function, like List::Util::max
in the middle of a large program that does lots of stuff. So if I do
use List::Util 'max';
At the top of my program, I'm stuck with that symbol, polluting my whole namespace, even though I only need it in one subroutine.
So I've been thinking of trying a different pattern, instead:
use List::Util ();
# a whole bunch of stuff later...
sub blah {
List::Util->import( 'max' );
$blah = max @foobar;
...
}
There are two problems with this, though. For one, it doesn't automatically unimport at the end of the block (drat.) I would have to undo everything with an unimport
.
The other problem is that apparently prototypes don't get applied correctly, so I have to say max( @foobar )
instead of the prettier parenthesisless version.
Is there an easy way to temporarily import symbols for a block, which would automagically ma开发者_JAVA百科ke them go away at the end of the block, and which would also handle prototypes correctly?
Just do this, it's much better and cleaner:
package Foo;
use strict; use warnings;
use List::Util 'max';
use namespace::autoclean;
# your method definitions here...
namespace::autoclean will "unimport" the symbol after the package's compilation cycle is done. The call to it in your method will still work, but you have no namespace pollution (the *Foo::max
symbol is removed) and calling $obj->max()
will fail.
Alternatively, you might want to take a look at Lexical::Import (I know nothing about it; an irc birdie mentioned it).
If you only use max in one subroutine, I wouldn't import it into the namespace at all. My solution is to
use List::Util;
sub blah {
print List::Util::max(@list);
}
You can localize a symbol table entry:
use List::Util ();
@y = qw(1 3 5 -9 4);
sub max { # return maximum *absolute value* of list
my $max = abs(shift);
$max<abs($_) && ($max=$abs($_)) for @_;
return $max;
}
sub max2 {
local *max = *List::Util::max;
return max(@_);
}
print "My max: ", max(@y), "\n"; # ==> 9
print "List::Util::max ", max2(@y), "\n"; # ==> 5
perlfunc implies that no MODULE
should do what you want:
sub blah {
use List::Util qw(max);
say max @foobar;
no List::Util;
}
but that doesn't work -- at least not for List::Util. I believe that it would need to define an unimport
method. Even then, I'm not sure if you could have a bare max
in your module call different definitions.
精彩评论