Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris

Problems importing constants in multiple namespaces

by Weevil (Novice)
on Aug 19, 2004 at 18:13 UTC ( #384405=perlquestion: print w/replies, xml ) Need Help??

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

Hello monks, my problem is as follows. I have a module (let's call it Module), which has a few sub-modules (let us call them Module::Monkey and Module::Ape).

Module exports some constants through use constant using Exporter. The code looks like this:
# package Module; require Exporter; # Make sure these modules are available to any script that does "use M +odule;": use Module::Monkey; use Module::Ape; use vars qw(@EXPORT @EXPORT_OK %EXPORT_TAGS @ISA); @ISA = qw(Exporter); @EXPORT = qw( MDB_INT MDB_FLOAT MDB_STRING ); use constant { MDB_INT => 0, MDB_FLOAT => 1, MDB_STRING => 2, }; # bla bla bla... 1;
If I use Module; in main, the constants are imported just fine. However, if I use Module; in Module/ or Module/, the constants are not imported. I suspect it's because I did use Module::Monkey; and use Module::Ape; in, and this is processed before the code to export the constants ever gets done. I tried putting the exporting code inside a BEGIN block, but that did not fix the problem, and surely if I put use Module; in Module/, the constants should be re-imported regardless of whether has already been loaded.

Currently, my only solution that works is to define the constants in a seperate package file and use that in all my modules that need the constants (kind of like a .h file in C), but that seems a messy way of doing things. Is there an accepted way of defining constants that work across all my sub-packages? Am I being silly by doing use Module::Monkey; and so on in and then doing use Module; in Module/ to import Module's constants?

Man, I hope I explained that right, it's confusing the heck out of me. I hope you can guide me.

Replies are listed 'Best First'.
Re: Problems importing constants in multiple namespaces
by ysth (Canon) on Aug 19, 2004 at 21:36 UTC
    There's nothing wrong with your approach. You just need to make a couple changes.

    First, put everything that has to do with exporting first. In this case, that is everything except the use Module::Monkey, and use Module::Ape.

    Secondly, if you are going to load at compile time anything that needs to recursively use your module (as Module::Monkey and Module::Ape do), make sure you've set up everything for exporting at compile time. In this case, change "require Exporter" to "use Exporter ()", and put the setting of @ISA and @EXPORT in a BEGIN block.

    With those changes, you should be just fine. Separating out your constants to a different module is a nice idea, and it's fairly easy to get Module to pass them along to things that import Module also, but it isn't necessary (and does take slightly more memory, if you are dealing with mod_perl or the like.)

      Thanks! This solution worked fine.

      I was sure I had to do something with BEGIN.
Re: Problems importing constants in multiple namespaces
by Joost (Canon) on Aug 19, 2004 at 20:43 UTC
    You might get away with explicitly importing in your sub classes, but it might still not work, because of the order in which import() will be called, if it gets called at all, see below:
    package Module::Monkey; use base 'Module'; BEGIN { Module->import(); }

    Note that use base does NOT call import() on the superclass.

    You're trying to use Module as a base class, and as a holder of constants to be exported, and as a "module loader" that loads all its subclasses. Life would be a lot simpler if you would drop at least one of these functions in another module, and I would recommend splitting them all out, which will make your code a lot saner:

    # in Module/ package Module::Loader; use Module; use Module::Monkey; use Module::Ape; use Module::Constants; # in package Module; use Module::Constants; sub some_inhereted_sub { }; # in Module/; package Module::Constants; use constant { MDB_INT => 0, MDB_FLOAT => 1, MDB_STRING => 2, }; # in Module/Ape; package Module::Ape; use Module::Constants; use base Module;


    Hope this helps,

Re: Problems importing constants in multiple namespaces
by naChoZ (Curate) on Aug 19, 2004 at 18:22 UTC

    I believe you have it backwards. I'm no expert yet, but I think it should be:

    package Module; ... package Module::Monkey; use base 'Module'; ... package Module::Ape; use base 'Module'; ...

    Update, book suggestion:
    By the way, I would highly recommend the alpaca book that Merlyn wrote. I've just finished my first cover-to-cover read of it and it has finally pried my feeble mind open and made me understand things that I just couldn't wrap my brain around from reading other things.

    "A long habit of not thinking a thing wrong, gives it a superficial appearance of being right." -- Thomas Paine

Re: Problems importing constants in multiple namespaces
by dragonchild (Archbishop) on Aug 19, 2004 at 18:23 UTC
    Am I being silly by doing use Module::Monkey; and so on in and then doing use Module; in Module/ to import Module's constants?


    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

    I shouldn't have to say this, but any code, unless otherwise stated, is untested

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://384405]
Approved by Limbic~Region
Front-paged by ysth
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (5)
As of 2020-10-24 01:19 GMT
Find Nodes?
    Voting Booth?
    My favourite web site is:

    Results (242 votes). Check out past polls.