alextor has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I'm including a file with some subroutines in my program using require, and I'm also including a module that has the same file in it using require.

It looks like this;

use lib("/usr/local/shlib/");

use Modis::ParseMe;

require '/usr/local/shlib/AL/subs.pl';

Inside ParseMe.pm I also have require '/usr/local/shlib/AL/subs.pl';

When I run the program and use one of the subroutines subs.pl, the output I get is "Undefined subroutine &main::mysub"

If I comment out "use Modis::ParseMe;", it works fine.

What can I do to fix this?

Thanks

  • Comment on Using require in a module and alongside that module in a program

Replies are listed 'Best First'.
Re: Using require in a module and alongside that module in a program
by Tanktalus (Canon) on Aug 12, 2011 at 22:37 UTC

    What you can do to fix it, for starters, is stop putting shared functionality in a .pl file. It's a lot less confusing if you follow convention. Further to that convention is to put your shared code in its own package. And if you want to export it to the caller's namespace, check Exporter (or any number of similar modules, such as Perl6::Export::Attrs).

    What's happening is that inside Modis/ParseMe.pm, you require the file. The subs.pl file gets loaded, everything gets inserted into your Modis::ParseMe namespace (since that's the package in effect when subs.pl is loaded). Then, back in main, you require it again. However, perl sees that it's already loaded, and doesn't reload it. Thus no functions are inserted into the main namespace (package).

    If you put them into an exportable namespace and use the module, both places can use it, and both places will work.

    Technically, if you put a package at the top of subs.pl, that should work, but you're going against convention. I'd encourage you to go with a module instead.

Re: Using require in a module and alongside that module in a program
by kennethk (Abbot) on Aug 13, 2011 at 14:44 UTC
    First off, as it appears you are just using subs.pl as an import/export mechanism, you really should follow Tanktalus's advice and use Exporter. Since you desire to export from subs.pl into both Modis::ParseMe and main, you might consider modifying ParseMe.pm to optionally export the desired subroutines.

    If this is a get-it-done moment and not for the long term, you can make the import happen with do instead of require. require 'file'; is essentially do 'file' or die "Can't locate file in \@INC"; with some extra overhead to make it happen only once.

      Thanks for the replies, I'll try to get Tanktalus's method implemented.

      If in the main program I use 'do' on the file instead of 'require', does it take that library away from Modis::ParseMe?

      Thanks

        If you use do, you literally execute the contents of the file in your current context, very similar to a straight in-lining. The interpreter will have no knowledge that the subroutines in your main program and in your Modis::ParseMe module should be related - you will essentially be using two identical, independent libraries.

        There are a number of drawbacks to this approach; for example, if your subs from subs.pl use closures, there will be no relationship between the variables wrapped in main and in Modis::ParseMe. Thus, if you are talking about a long term solution, you want use an Exporter.

Re: Using require in a module and alongside that module in a program
by Anonymous Monk on Aug 13, 2011 at 08:46 UTC