Search code examples
perlimportlexical-scope

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?


Solution

  • 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