Bill Grates
Bill Grates

Reputation: 906

What do the chained namespace identifiers in Perl do?

I found a code snippet which goes like this:

package File::MP3;
use parent 'File';    # sets @File::MP3::ISA = ('File');
my $mp3 = File::MP3->new( 'Andvari.mp3', $data );
$mp3->save();

Here, I want to ask if File::MP3 is just a name (it is named that way just to show that it inherits from File)

OR

We have to name it that way if it inherits from File?

Upvotes: 0

Views: 120

Answers (2)

zdim
zdim

Reputation: 66901

The File::MP3 in the package declaration is just a name. However, if you want to use that package then the name matters. The use dispatches to require, for which the name in require EXPR is

If EXPR is a bareword, require assumes a .pm extension and replaces :: with / in the filename for you, to make it easy to load standard modules. This form of loading of modules does not risk altering your namespace.

Thus if you want to use File::MP3 then an MP3.pm file had better be in a File/ directory, which needs to be in one of (the absolute-path) directories listed in @INC.

The class File from which File::MP3 inherits has nothing to do with the directory File/. The use parent (see parent) independently specifies the package to load for the class File, and its File.pm file also has to be found in @INC.

The MP3.pm file with the package may well be in a Media/ directory, in which case it would be best named as package Media::MP3; and would be loaded with use Media::MP3; – and it can still inherit from the File class by use parent File;

Placing file-related modules in a directory named File does make sense, of course.

Upvotes: 2

Borodin
Borodin

Reputation: 126742

Update

I made a module named Module.pm in lib folder, & then named the package as package lib::Module

You're getting a little confused

When use or require is actioned, Perl will form a relative path from the package name by changing something like My::Other::Module to My/Other/Module.pm using the obvious substitutions

It will look for that relative path in the list of locations in the built-in @INC array, which contains some paths that were defined when perl was built and others that may be added at run time

Up until very recently, @INC contained the current working directory, ., so if you have your module in ./lib/My/Other/Module.pm then the Perl compiler will find it if you use lib::My::Other::Module.pm. But that's not how it's meant to work

You should add ./lib to @INC (using either use lib './lib'[1] or by adding to the value of the environment variable PERL5LIB) and then use My::Other::Module. That will work fine because perl is looking for the .pm file in in ./lib. The name and path to the .pm file, the package statement, and the use statement should all agree about what the name is

[1] Note that it is a security risk to add relative paths to @INC. That is why . is no longer included as standard in the release client for Perl v5.26. That means you shouldn't use lib './lib' as described above. Instead you need something like use lib '/var/users/Me/Perl/source/lib'



A package name like File::MP3 is just a name. Perl's only requirement is that it has to be unique

But modules are grouped into families in CPAN, and most file-related modules begin with File::. There is also Win32::, Net::, Math:: etc.

It is also used to indicate subsidiary modules in a suite. For instance, Mojo::Message contains the code common to both Mojo::Message::Request and Mojo::Message::Response. But that is a mnemonic for the programmer's convenience only

In the case of Math::Poisson, perl will look for a file Math/Poisson.pm which should have a package declaration package Math::Poisson. If you use that package name elsewhere then anything you declare will be inserted into the module's namespace

Upvotes: 3

Related Questions