Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get Perl to give a warning message when a certain package/tag is imported?

I have a package that I just made and I have an "old-mode" that basically makes it work like it worked before: importing everything into the current namespace. One of the nice things about having this as a package is that we no longer have to do that. Anyway, what I would like to do is have it so that whenever anyone does:

use Foo qw(:oldmode);

I throw a warning that this is deprecated and that they should either import only what they need or just access functions with Foo->fun();

Any ideas on how to do this?

like image 811
Frew Schmidt Avatar asked Oct 09 '08 14:10

Frew Schmidt


2 Answers

You write your own sub import in package Foo that will get called with the parameter list from use Foo.

An example:

package Foo;
use Exporter;

sub import {
    warn "called with paramters '@_'";

    # do the real import work
    goto &{Exporter->can('import')};
}

So in sub import you can search the argument list for the deprecated tag, and then throw a warning.

Update: As Axeman points out, you should call goto &{Exporter->can('import')}. This form of goto replaces the current subroutine call on the stack, preserving the current arguments (if any). That's needed because Exporter's import() method will export to its caller's namespace.

like image 168
moritz Avatar answered Oct 06 '22 18:10

moritz


Well, as you specifically state that you want to alarm in the cases of use Mod qw<:oldmode>; This works better:

package Foo;
use base qw<Exporter>;
use Carp qw<carp>;
...
sub import { 
    #if ( grep { $_ eq ':oldmode' } @_ ) { # Perl 5.8
    if ( @_ ~~ ':oldmode' ) {              # Perl 5.10 
        carp( 'import called with :oldmode!' );
    }
    goto &{Exporter->can( 'import' )};
}

Thanks to Frew, for mentioning the Perl 5.10 smart match syntax. I'm learning all the ways to work Perl 5.10 into my code.

Note: the standard way to use exporter in an import sub is to either manipulate $Exporter::ExportLevel or to call Foo->export_to_level( 1, @_ ); But I like the way above. It's quicker and, I think, simpler.

like image 21
2 revs Avatar answered Oct 06 '22 19:10

2 revs