tags:

views:

97

answers:

4

I've written a special import function that will be used in a few places and I'd like to be able to just go "use ImportRenamer;" in those modules and have them use the import gained from ImportRenamer henceforth. How would i go about that?

Edit: In other words: How do i import 'import' without running it?

+2  A: 

UPDATE

Now that OP clarified his needs, this should indeed be done in a way similar to what Exported does, to be precise, by injecting the sub reference into a caller's namespace via a glob assignment. Example:

###############################################

package ImportRenamer; 
use strict;
sub import_me {
   print "I am a cool importer\n";
}

sub import { 
  my ($callpkg)=caller(0);
  print "Setting ${callpkg}::import to ImportRenamer::import_me\n"; 
  no strict "refs";
  *{$callpkg."::import"} = \&ImportRenamer::import_me; # Work happens here!!!
  use strict "refs";
}
1;

###############################################

package My; 
use strict;
use ImportRenamer; 
1;

###############################################

package My2; 
use strict;
use ImportRenamer; 
1;

###############################################

And the test:

> perl -e '{  package main; use My; use My2; 1;}'
Setting My::import to ImportRenamer::import_me
I am a cool importer
Setting My2::import to ImportRenamer::import_me
I am a cool importer

ORIGINAL ANSWER

You don't need to do anything special beyond calling the import method "import". use already calls import(), see perldoc use:

use Module LIST 

Imports some semantics into the current package from the named module, generally by aliasing certain subroutine or variable names into your package.

It is exactly equivalent to:

 BEGIN { require Module; Module->import( LIST ); }
DVK
I don't think this answers the OP's question. It seems to me that his problem is more, "How do I hide the build-in `import` with my module?"
JSBangs
As JSBangs says. Your answer tells me how to *run* import from outside. I want to import 'import'.
Mithaldu
@mithaldu - OK, just to confirm - do you want to have a sub called "import" in module "ImportRenamer", and (1) NOT run it when you do "use ImportRenamer" in a module called "MyModule1"; and (2) when you do `use MyModule`, it will run `ImportRenamer::import()` instead of `MyModule::import()`?
DVK
@DVK: Correct. I'm not particularly picky what "import" is called in ImportRenamer, but i want to be able to go "use ImportRenamer;" in MyModule, so MyModule::import becomes the function that ImportRenamer exports.Maybe i should look at how Exporter does it.
Mithaldu
@JSBangs - OK, now I git it. Updated
DVK
+2  A: 

How about something like this:

package Your::Module;

use strict;
use warnings;

sub import { 
    # gets called by use Your::Module
    my ( $pkg ) = caller;

    no strict 'refs';
    *{ $pkg . '::import' } = \&_real_import;
}

sub _real_import { 
    # import function to be exported to caller
    print "blah blah";
}

This manually assigns the _real_import sub to the import slot of the calling package's namespace. If you do this in a BEGIN block, then the import sub should be ready and waiting when that package gets used.

friedo
+3  A: 

You need to write a custom import method in your module that will export your function you want to be called import in the calling namespace.

Here's some untested code:

package ImportMe;

sub import { 

    # Get package name
    my $caller = caller;

    # Install my_import into the calling package as import
    {    no strict 'refs';
         *{"${caller}::import"} = \&my_import;
    }

    return 1;
}

# renamed as import when installing
sub my_import {

   # do stuff

}

Now you can put use ImportMe; in all your modules and an import method will be installed.

daotoad
+4  A: 

As an alternative, you can avoid mucking around in the symbol table by using Sub::Exporter

package Your::Module;

use Sub::Exporter (
    -setup => {
        exports => {
            import => sub { return \&_real_import }
        },
        # the "default" group auto-exports "import" without the caller 
        # specifically asking for it
        groups => { default => [qw(import)] },
    }
);

sub _real_import { ... }

EDIT: added the "default" group for auto-exporting

Brian Phillips