Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does a function name have to be specified in a use statement?

In perl, sometimes it is necessary to specify the function name in the use statement.

For example:

use Data::DPath ('dpath');

will work but

use Data::DPath;

won't.

Other modules don't need the function names specified, for example:

use WWW::Mechanize;

Why?

like image 765
CJ7 Avatar asked Dec 25 '22 02:12

CJ7


2 Answers

Each module chooses what functions it exports by default. Some choose to export no functions by default at all, you have to ask for them. There's a few good reasons to do this, and one bad one.

If you're a class like WWW::Mechanize, then you don't need to export any functions. Everything is a class or object method. my $mech = WWW::Mechanize->new.

If you're a pragma like strict then there are no functions nor methods, it does its work simply by being loaded.

Some modules export waaay too many functions by default. An example is Test::Deep which exports...

all any array array_each arrayelementsonly arraylength arraylengthonly bag blessed bool cmp_bag cmp_deeply cmp_methods cmp_set code eq_deeply hash hash_each hashkeys hashkeysonly ignore Isa isa listmethods methods noclass none noneof num obj_isa re reftype regexpmatches regexponly regexpref regexprefonly scalarrefonly scalref set shallow str subbagof subhashof subsetof superbagof superhashof supersetof useclass

The problem comes when another module tries to export the same functions, or if you write a function with the same name. Then they clash and you get mysterious warnings.

$ cat ~/tmp/test.plx
use Test::Deep;
use List::Util qw(all);

$ perl -w ~/tmp/test.plx
Subroutine main::all redefined at /Users/schwern/perl5/perlbrew/perls/perl-5.20.2/lib/5.20.2/Exporter.pm line 66.
 at /Users/schwern/tmp/test.plx line 2.
Prototype mismatch: sub main::all: none vs (&@) at /Users/schwern/perl5/perlbrew/perls/perl-5.20.2/lib/5.20.2/Exporter.pm line 66.
 at /Users/schwern/tmp/test.plx line 2.

For this reason, exporting lots of functions is discouraged. For example, the Exporter documentation advises...

Do not export method names!

Do not export anything else by default without a good reason!

Exports pollute the namespace of the module user. If you must export try to use @EXPORT_OK in preference to @EXPORT and avoid short or common symbol names to reduce the risk of name clashes.

Unfortunately, some modules take this too far. Data::DPath is a good example. It has a really clear main function, dpath(), which it should export by default. Otherwise it's basically useless.

You can always turn off exporting with use Some::Module ();.

like image 61
Schwern Avatar answered Dec 27 '22 10:12

Schwern


The reason is that some modules simply contain functions in them and they may or may not have chosen to export them by default, and that means they may need to be explicitly imported by the script to access directly or use a fully qualified name to access them. For example:

# in some script
use SomeModule;
# ...
SomeModule::some_function(...);

or

use SomeModule ('some_function');
# ...
some_function(...);

This can be the case if the module was not intended to be used in an object-oriented way, i.e. where no classes have been defined and lines such as my $obj = SomeModule->new() wouldn't work.

If the module has defined content in the EXPORT_OK array, it means that the client code will only get access to it if it "asks for it", rather than "automatically" when it's actually present in the EXPORT array.

Some modules automatically export their content by means of the @EXPORT array. This question and the Exporter docs have more detail on this.

Without you actually posting an MCVE, it's difficult to know what you've done in your Funcs.pm module that may be allowing you to import everything without using EXPORT and EXPORT_OK arrays. Perhaps you did not include the package Funcs; line in your module, as @JonathanLeffler suggested in the comments. Perhaps you did something else. Perl is one of those languages where people pride themselves in the TMTOWTDI mantra, often to a detrimental/counter-productive level, IMHO.

The 2nd example you presented is very different and fairly straightforward. When you have something like:

use WWW::Mechanize;
my $mech = new WWW::Mechanize;
$mech->get("http://www.google.com");

you're simply instantiating an object of type WWW::Mechanize and calling an instance method, called get, on it. There's no need to import an object's methods because the methods are part of the object itself. Modules looking to have an OOP approach are not meant to export anything. They're different situations.

like image 21
code_dredd Avatar answered Dec 27 '22 10:12

code_dredd