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

I have a question about packages. Say, I have a directory ./perl/lib/MyPackage with packages Package1.pm, Package2.pm, Package3.pm in it. When I'm referring Package2 from Package1, I have to do it this way:
use MyPackage::Package2;
Is there a way to refer to that package without referring to the parent directory? These packages are in the same directory after all. I want to refer to the "sibling" packages by "use Package2" (resembles Java packaging). I tried defining these packages by package MyPackage::Package1;. It didn't work that way either. I've read the "perlmod" - it's not stated explicitly there.

Replies are listed 'Best First'.
Re: "Packaging" Perl modules
by davorg (Chancellor) on Jan 23, 2003 at 12:07 UTC

    No, you can't do that. Perl package names imply nothing about relationships between modules. As a convenience they map onto file names relative to a directory in @INC, but you can't make any other assumptions.

    --
    <http://www.dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

Re: "Packaging" Perl modules
by Pardus (Pilgrim) on Jan 23, 2003 at 12:49 UTC
    package Package1; require "Package2.pm"; import Package2;
    This should be identical with use Package2
    --
    Jaap Karssenberg || Pardus (Larus)? <pardus@cpan.org>
    >>>> Zoidberg: So many memories, so many strange fluids gushing out of patients' bodies.... <<<<
Re: "Packaging" Perl modules
by ihb (Deacon) on Jan 23, 2003 at 17:06 UTC

    The use keyword is quite simple in its idea. It just looks up a file, and then issues an import call on that package. It will look in the directories listed the @INC array, which you can modify through the lib pragma. This means that use MyPackage::Package2; will look for MyPackage/Package2.pm. But it will also issue an import call on MyPackage::Package2, MyPackage::Package2->import(), but that will do nothing, because in Package2.pm you have package Package2; (I presume). So there is no MyPackage::Package2 package.

    Changing package Package2; to package MyPackage::Package2; will just make the import call work right, but it won't make Package1 find Package2 through use Package2;, since the lookup is done through the file system. This also won't make it possible to move modules around to different "packages", (java-style packages).

    So what you really want to do is to keep your packages named whatever you want them to be. The way to make them all use()able is by using the lib pragma. @INC is a global variable, and all packages will share it, so if one package can use Package1;, then all other can too. This means that the problem will solve itself once the first modules is loaded if loaded via use, since that will make sure that MyPackage is in @INC.

    Hope I've helped,
    ihb
Re: "Packaging" Perl modules
by crouchingpenguin (Priest) on Jan 23, 2003 at 15:13 UTC
    I think what you want is:

    use lib "/perl/lib/MyPackage";

    before all of your 'use' lines so that '/per/lib/MyPackage' is in @INC. Then you simply 'use' the package name as defined with the 'package $name;' line within each module/package.

    "Never be afraid to try something new. Remember, amateurs built the ark. Professionals built the Titanic."
Re: "Packaging" Perl modules
by leriksen (Curate) on Jan 23, 2003 at 22:55 UTC
    There are really two concepts in Perl's packaging and namespace system that are intertwinned, and that seems to cause confusion.
    The concepts are
    1. where is the package? The @INC array is what Perl searches to locate your package
    2. how is this package related to other packages? Some people believe that the 'use A::B::C;' notation indicates that C is a related to B, which is related to A, ala OO inheritance. This can be the case, but generally is not. Perl does not dicatate either way. More later.
    For 1, you have a couple of options
    a. put all the packages in one spot, and add that location to the @INC array.
    b. make directories below an entry in @INC, and specify the directory path in the scripts/modules
    Thus for a, you could have a directory off perl/lib called projectA, and in there you could put moduleA, moduleB,etc. Add perl/lib/projectA to @INC, then specify the module you need in your script as 'use moduleA;' etc
    And for b, you leave @INC unchanged, but put 'use projectA::moduleA;' in your code.

    So the 'use A::B::C;' in your scripts really only indicates the path below an @INC entry to search. It does not imply that if the code 'knows' where A::B is, it should be possible to just say 'use C;'. The module locating code in Perl will still complain.

    For 2, how are modules related, Damian Conways quote is - I think Mark-Jason Dominus said it best when he pointd out that Newton::Isaac is not related to Newton::John::Olivia. - end quote
    If you want to indicate that a module is 'related' to another, use the @ISA array
    package Newton; # methods and class attributes supported by all Newtons ... sub be_famous { } package Issac; # inherit things Newtons can do @ISA qw(Newton); # methods and class attributes supported by Newton::Issac instances ... sub progress_physics { } package John; @ISA qw(Newton); # no methods/attributes, by themselves Newton::John's can just be famo +us (inherited from Newton) package Olivia; @ISA qw(John); # methods and class attributes supported by Newton::John::Olivia insta +nces ... sub sing_like_a_bird { }
    Each of these packages may or may not be OO, but the @ISA expresses a relationship when it comes to resolving method calls - for a fantastically crystal clear explanation see Damian Conways Object Oriented Perl by Manning (ISBN 1884777791) - ,but it does not dictate where the packages are, only @INC does that. In this case, you need to specify all the locations in @INC (if they are all in different directories) or make one addition to @INC, (if they are all in one directory), or make no changes to @INC, and put them all in a location in the standard @INC (not recommended, it is possible that you'll clobber a standard module that happens to have the same name as one of yours, or a CPAN module installation clobbers one of yours)
    So remember, the 'use A::B::C;' just specifies the path below an @INC entry to search, not a relationship between A or B or C. They MAY BE related, but that is NOT determined by the use syntax. That is best done by @ISA, if an inheritance scheme is appropriate.
    Setting @INC can be done in many ways, the most common is via 'use lib qw(... paths ...), or (my preferred way, stops coding of paths in scripts) by setting PERL5LIB in my shell ( if the platform supports the concept of a shell), or by manipulating @INC directly via
    <code> push @INC, $new_path; # add to back of search path unshift @INC, $new_path; # add to front of search path <\code>