export vs export_ok in perl

2019-02-02 22:22发布

问题:

I can not understand what is the difference/use case of EXPORT_OK vs EXPORT.
Most resources mentions something in the lines of:

@Export allows to export the functions and variables of modules to user’s namespace using the standard import method. This way, we don’t need to create the objects for the modules to access its members.
@EXPORT_OK does export of symbols on demand basis for selective list of symbols (subroutines and variables) of the module.

But I really don't see the difference/meaning here.
Can someone please provide a small fundamental example of the difference/usage of these 2 symbols?

回答1:

Let's say I have a package MyPackage that uses @EXPORT.

#this is MyPackage.pm
package MyPackage;
@EXPORT = qw(do_awesome_thing);

sub do_awesome_thing { ... }

sub be_awesome { ... }

Now, when I use MyPackage in my code,

#this is myscript.pl
use MyPackage;

do_awesome_thing(); #works

be_awesome(); #doesn't work
MyPackage::be_awesome(); #works

do_awesome_thing gets automatically exported to my code from MyPackage, without me having to say "give this to me". be_awesome isn't exported (and it won't be exported with @EXPORT_OK either, I'm just showing that part to get you clear on what "exporting" gives us).

On the other hand, if I have a package MyOtherPackage that uses @EXPORT_OK,

#this is MyOtherPackage.pm
package MyOtherPackage;
@EXPORT_OK = qw(do_awesome_thing);

sub do_awesome_thing { ... }

sub be_awesome { ... }

and then try

#this is mynewscript.pl
use MyOtherPackage;

do_awesome_thing(); #doesn't work
MyOtherPackage::do_awesome_thing(); #works, as always

the line calling do_awesome_thing directly won't work. This is because putting something in @EXPORT_OK says "give this to my users only if they ask for it". Since we've just said use MyOtherPackage without explicitly asking for do_awesome_thing to be imported here, it doesn't get imported, and is accessible only by specifying the package name.

The way you ask for do_awesome_thing to be imported is to say use MyOtherPackage qw(do_awesome_thing) in the second line of mynewscript.pl above. This says import that module and make do_awesome_thing available directly. After that, the fourth line in mynewscript.pl above will start working.

Note that the user can specify use MyPackage qw(do_awesome_thing) with the first package also, and in that case, anything else in the @EXPORT list won't be exported, only do_awesome_thing will be. So, except for the default case of use PackageName;, @EXPORT and @EXPORT_OK behave similarly. In the default case, anything in @EXPORT gets thrown into the user's script automatically, while @EXPORT_OK is more polite and doesn't export anything.



回答2:

From the fine Exporter manual:

  • use YourModule;
    This imports all the symbols from YourModule's @EXPORT into the namespace of the use statement.
  • use YourModule ();
    This causes perl to load your module but does not import any symbols.
  • use YourModule qw(...);
    This imports only the symbols listed by the caller into their namespace. All listed symbols must be in your @EXPORT or @EXPORT_OK, else an error occurs. The advanced export features of Exporter are accessed like this, but with list entries that are syntactically distinct from symbol names.

So, if you use @EXPORT and someone does the usual use YourModule;, then you've just polluted their namespace with everything in @EXPORT. But, if you use @EXPORT_OK, they have to specifically ask for things to be imported so the person using your module has control over what happens to their namespace.

The difference is really a matter of who controls what gets into the user's namespace: if you use @EXPORT then the module being used does, if you use @EXPORT_OK then the code doing the import controls their own namespace.

Of course, you could always say use Whatever(); to keep impolite modules from polluting your namespace but that's ugly and you shouldn't have to kludge around rude code that wants to scribble all over your namespace.