Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 make them go away at the end of the block, and which would also handle prototypes correctly?

like image 753
friedo Avatar asked Jun 14 '10 16:06

friedo


2 Answers

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).

like image 83
Ether Avatar answered Nov 15 '22 09:11

Ether


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);
}
like image 45
Mike Avatar answered Nov 15 '22 07:11

Mike