Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Subroutine reference in @INC

by IlyaM (Parson)
on Mar 21, 2002 at 21:39 UTC ( #153428=perlquestion: print w/ replies, xml ) Need Help??
IlyaM has asked for the wisdom of the Perl Monks concerning the following question:

I recall that once I've seen somewhere description of one undocumented(?) Perl feature which allows to do wierd things like loading Perl modules with use from, say, ZIP archive.

It is possible to put reference on subroutine in @INC and this subroutine will be called when Perl module is used (or required). This subroutine could implement loading of Perl modules from ZIP archive for example. Unfortunately I could not find description what interface should have such subroutine. That is what arguments are passed to it, what should this subroutine return, etc.

To prove that I'm not dreaming I wrote simple test script:

BEGIN { unshift @INC, sub { print "@_\n"; return }; } use Cwd;
It does print something which proves that subroutine reference in @INC does have some special meaning:
CODE(0x8116490) Cwd.pm CODE(0x8116490) strict.pm CODE(0x8116490) Carp.pm CODE(0x8116490) Exporter.pm CODE(0x8116490) base.pm CODE(0x8116490) warnings.pm
Does anybody have more info about it?

--
Ilya Martynov (http://martynov.org/)

Comment on Subroutine reference in @INC
Select or Download Code
Re: Subroutine reference in @INC
by gellyfish (Monsignor) on Mar 21, 2002 at 21:52 UTC

    Yep, you can do that but I think you are going to be looking at the forthcoming 5.8.0 release to be able to do that in the best fashion ...I am sorry but I can't find the stuff on this right now.

    /J\

      Thanks for hint about 5.8.0. I've just checked docs for 5.7.3 and I found description of this feature. It seems that interface is not going to be changed in 5.8.0. It just becomes documented.

      From perldoc -f require in 5.7.3:

      You can also insert hooks into the import facility, by putting directly Perl code into the @INC array. There are three forms of hooks: subroutine references, array references and blessed objects.

      Subroutine references are the simplest case. When the inclusion system walks through @INC and encounters a subroutine, this subroutine gets called with two parameters, the first being a reference to itself, and the second the name of the file to be included (e.g. "Foo/Bar.pm"). The subroutine should return "undef" or a filehandle, from which the file to include will be read. If "undef" is returned, "require" will look at the remaining elements of @INC.

      If the hook is an array reference, its first element must be a subroutine reference. This subroutine is called as above, but the first parameter is the array reference. This enables to pass indirectly some arguments to the subroutine. In other words, you can write:

      push @INC, \&my_sub; sub my_sub { my ($coderef, $filename) = @_; # $coderef is \&my_sub ... }

      or:

      push @INC, [ \&my_sub, $x, $y, ... ]; sub my_sub { my ($arrayref, $filename) = @_; # Retrieve $x, $y, ... my @parameters = @$arrayref[1..$#$arrayref]; ... }

      If the hook is an object, it must provide an INC method, that will be called as above, the first parameter being the object itself. (Note that you must fully qualify the sub's name, as it is always forced into package "main".) Here is a typical code layout:

      # In Foo.pm package Foo; sub new { ... } sub Foo::INC { my ($self, $filename) = @_; ... } # In the main program push @INC, new Foo(...);

      Note that these hooks are also permitted to set the %INC entry corresponding to the files they have loaded. See "%INC" in perlvar.

      --
      Ilya Martynov (http://martynov.org/)

(Ovid) Re: Subroutine reference in @INC
by Ovid (Cardinal) on Mar 21, 2002 at 22:12 UTC

    Whenever you find a need to do something tricky, there are two things you need to do. First, step back and ask yourself if, in solving your problem, you solution creates more potential problems. Remember, simple is better. Why do you want to load a module from a zip file? You're simply going to slow things down and unless you have some serious space problems, I seriously doubt that this solution will show great benefit. Further, by playing around with @INC, you can easily create a maintenance nightmare for someone else later down the road.

    If, after the first step you realize that you really have a need for this, figure out a way to do this that makes it clear to the programmer that something unusual is going on so they have a chance to follow what's going on. For example, if I see the following at the top of some code, I'd have a pretty clear idea that I need to dig deeper:

    use Archive::Module qw/ Some::Big::Module /;

    Then, in Archive::Module, you can stuff your real code and you won't need to play with @INC and possibly confuse the heck out of the poor programmer who has to maintain your code.

    Incidentally, I'd love to see your code when you put it together.

    Cheers,
    Ovid

    Update: After reading the response by Dominus, I feel less confident about use Archive::Module.... I wasn't aware that adding code refs to @INC was documented. I don't think I gave a bad answer, though, as it could potentially prove to be a very useful module.

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Re: Subroutine reference in @INC
by lestrrat (Deacon) on Mar 21, 2002 at 22:13 UTC

    I remember there was something called The::Net somewhere in the monestary that did just that to fetch modules from over the network... but for the life of me I can't find it.

      Coincidentally enough I was looking at this same subject a day or two ago. Abigail's The::Net can be found at this node.

      broquaint

Re: Subroutine reference in @INC
by Dominus (Parson) on Mar 21, 2002 at 22:31 UTC
    From the manual:

    You can also insert hooks into the import facility, by putting directly Perl code into the @INC array. There are three forms of hooks: subroutine references, array references and blessed objects.

    Subroutine references are the simplest case. When the inclusion system walks through @INC and encounters a subroutine, this subroutine gets called with two parameters, the first being a reference to itself, and the second the name of the file to be included (e.g. "Foo/Bar.pm"). The subroutine should return undef or a filehandle, from which the file to include will be read. If undef is returned, require will look at the remaining elements of @INC.

    If the hook is an array reference, its first element must be a subroutine reference. This subroutine is called as above, but the first parameter is the array reference. This enables to pass indirectly some arguments to the subroutine.

    In other words, you can write:

    push @INC, \&my_sub; sub my_sub { my ($coderef, $filename) = @_; # $coderef is \&my_sub ... }

    or:

    push @INC, [ \&my_sub, $x, $y, ... ]; sub my_sub { my ($arrayref, $filename) = @_; # Retrieve $x, $y, ... my @parameters = @$arrayref[1..$#$arrayref]; ... }

    If the hook is an object, it must provide an INC method, that will be called as above, the first parameter being the object itself. (Note that you must fully qualify the sub's name, as it is always forced into package main.) Here is a typical code layout:

    # In Foo.pm package Foo; sub new { ... } sub Foo::INC { my ($self, $filename) = @_; ... } # In the main program push @INC, new Foo(...);

    Note that these hooks are also permitted to set the %INC entry corresponding to the files they have loaded. See perlvar/%INC.

    For a yet-more-powerful import facility, see use and perlmod.

    --
    Mark Dominus
    Perl Paraphernalia

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://153428]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (8)
As of 2014-09-03 02:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite cookbook is:










    Results (35 votes), past polls