DEV Community

Cover image for Perl modules loading, calling or returning
Tib
Tib

Posted on

Perl modules loading, calling or returning

Modules (and CPAN) are one of the "killer feature" of Perl, this article will discuss module loading/calling and some subtleties around this topic.

Where modules live do not dictate how they are called.

It is something important to understand early when you learn Perl programming, how you will load a module does not dictate its future package name (how it will be called).

Let's start with a simple example with a empty module stored in a File.pm in a subdirectory:

Directory
└── Directory
    └── File.pm
Enter fullscreen mode Exit fullscreen mode

File.pm contains nothing but a true return value:

1;
Enter fullscreen mode Exit fullscreen mode

The import is done by pointing to the path of the pm file:

#!/usr/bin/env perl

use Directory::Directory::File;
Enter fullscreen mode Exit fullscreen mode

So far, all good! :D

But it is too simple, so let's continue with a more real world example that actually calls something:

package Directory::Directory::File;

sub foobar() {
        print "Foo Bar!\n";
}

1;
Enter fullscreen mode Exit fullscreen mode

It is imported and called like the following:

#!/usr/bin/env perl

# Import 
use Directory::Directory::File;

# Call
Directory::Directory::File::foobar();
Enter fullscreen mode Exit fullscreen mode

Notice that Directory::Directory::File::foobar(); matches the package declaration in the module file... Where actually when calling the modules functions/variables, we have to follow the package name decided by the author for its module (read the doc).

It could be Directory::Directory::File::foobar() or something totally different from the path.

Look at this new example:

Directory
└── Directory
    └── File.pm
Enter fullscreen mode Exit fullscreen mode

The module is stored in Directory/Directory/File.pm but belongs to package "Misleading" and declares/defines once again a function foobar:

package Misleading;

sub foobar() {
        print "Foo Bar!\n";
}

1;
Enter fullscreen mode Exit fullscreen mode

On importer side, the use and later the function call are not using the same "id" name:

#!/usr/bin/env perl

# Import 
use Directory::Directory::File;

# But package is actually named "Misleading" !!!
Misleading::foobar();

# WON'T WORK!
# Directory::Directory::File::foobar();
Enter fullscreen mode Exit fullscreen mode

N.B.: Please note that the good practice is to make match path and package name. But you can meet aliases

use vs require

The use and require are doing almost the same thing but at different phases.

The require documentation ends with "For a yet-more-powerful import facility, see use and perlmod."

The use keyword executes at compilation phase means before execution even if it's the last line of your program.

Here is my sample "Bazinga" module:

package Bazinga;

sub joke() {
    print "Bazinga!\n";
}

1;
Enter fullscreen mode Exit fullscreen mode

And trying to call the function joke before to actually load it works very well:

$ perl -I. -e 'Bazinga::joke(); use Bazinga;'
Bazinga!
Enter fullscreen mode Exit fullscreen mode

It would not be the same with imports at runtime.

$ perl -I. -e 'Bazinga::joke(); require Bazinga;'
Undefined subroutine &Bazinga::joke called at -e line 1.
Enter fullscreen mode Exit fullscreen mode

With runtime imports, I can also import conditionally a module.

The following example will reload a module:

require Bazinga;

joke();

# Is it already loaded?
if ($INC{"Bazinga.pm"}) {
    print "Press ENTER to reload module:";
    <STDIN>;
    delete $INC{"Bazinga.pm"}; # Remove it from list
    require Bazinga; # Reload it
    joke();
};
Enter fullscreen mode Exit fullscreen mode

When you run this code, it will import and execute joke then reload the module on "Enter" (and run joke again).
Since it reloads the module, I can even change the module (the content of the joke function) during the execution of the program:

sub joke() {
    print "Knock Knock Knock Penny!\n";
    print "Knock Knock Knock Penny!\n";
    print "Knock Knock Knock Penny!\n";
}

1;
Enter fullscreen mode Exit fullscreen mode

And everything becomes more dynamic:

Bazinga!
Press ENTER to reload module:    
Knock Knock Knock Penny!
Knock Knock Knock Penny!
Knock Knock Knock Penny!
Enter fullscreen mode Exit fullscreen mode

Perl module return value

Modules have to return a "true" value, it sometimes confuse beginners, but I read somewhere that it comes from Perl 4 where importing a module was much more like executing a subscript.

So what if we try to return a "false" value?

0;
Enter fullscreen mode Exit fullscreen mode

When importing it, we get in trouble:

$ perl -I. -e 'use Boom;'
Boom.pm did not return a true value at -e line.
BEGIN failed--compilation aborted at -e line 1.
Enter fullscreen mode Exit fullscreen mode

Why are there is 2 messages here?
There is one about importing and one about compilation because of the "phases" I mentioned just above.

Just replace use per require to change the phase where the import is processed and it will now only print the import failure:

$ perl -I. -e 'require Boom;'
Boom.pm did not return a true value at -e line 1.
Enter fullscreen mode Exit fullscreen mode

Some people are playing with modules return codes like Michael G Schwern see his stackoverflow response or more recently PEVANS with a 0x55AA in its Faster::Math

You can find more example of return values thanks to Acme::ReturnValue

-M

You can import a module with command line switch -M like the following:

$ perl -I. -MBazinga -e 'joke()'
Bazinga!
Enter fullscreen mode Exit fullscreen mode

Visibility

Namespace pollution and symbols export is an important topic that I will not discuss today but I leave you in a good company 😀

Oldest comments (8)

Collapse
 
grinnz profile image
Dan Book

Slightly confusing to use the term "import" here since that references a specific functionality (which use executes in addition to loading, but require does not). Here you are just talking about loading modules, not importing them, these are two different steps.

Collapse
 
thibaultduponchelle profile image
Tib

Ok, I edited a bit to try to avoid confusion 👍

Collapse
 
domm profile image
domm

A long time ago I did a talk on that subject: domm.plix.at/talks/2005_braga_usin...

I think a lot of it is still relevant...

Collapse
 
thibaultduponchelle profile image
Tib • Edited

Oh thank you!! 🙏 I will have a look

Collapse
 
matthewpersico profile image
Matthew O. Persico
$ perl -I. -e 'Bazinga::joke(); use Bazinga;'
Bazinga
It would not be the same with imports at runtime.
$ perl -I. -e 'Bazinga::joke(); require Bazinga;'
Undefined subroutine &Bazinga::joke called at -e line 1.

That is the best demonstration I have every seen for the difference between use and require.

Collapse
 
thibaultduponchelle profile image
Tib

Thank you a lot 😃

Collapse
 
tobyink profile image
Toby Inkster

One of my favourite ways to return a true value from a module is:


__PACKAGE__
__END__

Enter fullscreen mode Exit fullscreen mode

Yes, no semicolon.

Collapse
 
thibaultduponchelle profile image
Tib

I have to admit, it confuses me