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

Hello monks I am curious about a little question to do with how PERL deals with compilation of modules. I'm not sure specifically how to state the question as I have only just begun to perceive that the question exists. Lets say you have a module;
package Model::Conf; use Exporter; use base 'Exporter'; our @EXPORT = qw( $conf ); our $conf = { 'somevar' => 'somevalue' }; $conf->{'foo'} = bar(); sub bar() { return 'bar'; } 1;
does the subroutine "bar" run every time I put use Model::Conf in other packages? If so, and assuming I want the code only to run once at compile time and its result to be accessible in any other package I put use Model::Conf in, would the following be correct;
package Model::Conf; use Exporter; use base 'Exporter'; our @EXPORT = qw( $conf ); our $conf = { 'somevar' => 'somevalue' }; $conf->{'foo'} = bar() unless $conf->{'foo'}; sub bar() { return 'bar'; } 1;
The reason I ask is that I want to be able to put use Model::Conf in various other packages without the sub "bar" being run each time and wasting OPCODES on a very tight little MVC 'micro'-framework I am working on for the educational benefit, and I am not sure if the above is the right way to be going or what. Any thoughts? Many thanks.

Replies are listed 'Best First'.
Re: package compiling
by Eliya (Vicar) on Apr 13, 2011 at 16:55 UTC
    does the subroutine "bar" run every time I put use Model::Conf in other packages?

    If you use or require the module, Perl keeps tracks of already loaded modules (in %INC), so the code is loaded/compiled/executed only once.

    (do EXPR also adds an entry in %INC, but doesn't check itself before loading, so with do the module's code would be executed several times.)

      That's exactly what I needed to know thanks! Now I'm wondering if there is anything cool I can with this %INC variable... hrm I'll have to have a think about that.

        One "cool" thing you can do with %INC is to print out a comprehensive list of modules (including dependencies) and where they have been loaded from, by putting the following in your script:

        END { say for sort values %INC; }

        (useful for debugging, or just to explore how things work)

Re: package compiling
by afoken (Chancellor) on Apr 14, 2011 at 09:59 UTC

    Some notes:

    • use base loads the base class if it is not already loaded, so you do not need to explicitly load it before.
    • use base does much more than just loading a base class and setting up inheritance, and most times, you don't need that. use parent loads the base class and sets up inheritance, and that's all it does. So I would recomment to use parent instead of base.
    • There is no need to inherit from Exporter at all (unless you want to support perl 5.8.2 and older), use Exporter 'import' is sufficient for your code and most other cases. (See also Re: Advice on style and Re^2: Advice on style).

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
      For clarity and for other potential readers would this be a better implementation?
      package Model::Conf; use Exporter 'import'; our @EXPORT = qw( $conf ); our $conf = { 'somevar' => 'somevalue' }; $conf->{'foo'} = bar(); sub bar() { return 'bar'; }

        Add ...

        use strict; use warnings;

        ... and perhaps ...

        use 5.008_003;

        (because older perls may have older Exporters), then the code looks quite good.

        Next step is to think about stopping exporting without explicit request (i.e. move exports from @EXPORT to @EXPORT_OK, think about %EXPORT_TAGS, learn about tag handling utility functions in Exporter).

        Then, you could re-think your design. Do you really need to export a variable? Perhaps an object is a much better solution for your problem.

        On the other hand, sometimes exporting a variable is the best solution. In some situations, exporting it by default is even better than exporting on demand.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)