9

I have a module called hsfSubs.pm in my perl\lib folder. I have nothing in the module but subroutines and 1; at the end.

One subroutine, for example, is named pause. I have implemented no import or export routines.

In my main programs, I simply say use hsfSubs;, and I am subsequently able to call pause with no problem. Ditto if I say use hsfSubs qw(pause);.

Why would I need to use Exporter, @EXPORT and @EXPORT_OK, etc. or any other complications?

The multiple answers on Stack Overflow to questions about Exporter tell how to use it, but I fail to see why to use it.

ThisSuitIsBlackNot
  • 23,492
  • 9
  • 63
  • 110
user1067305
  • 3,233
  • 7
  • 24
  • 29

1 Answers1

13

The short version is that you wanted a module, but you ended up with what this calls a library. These aren't good because they pollute their caller's namespace (which can cause plenty of problems). But more crucially here, loading them using require or use (as oppose to do) is buggy.

If it had been properly written as a module, your example would not work. Exporter is the solution to that problem.


Let's dive into the details.

Like I said, there's a problem with your module. As you've noticed, it sometimes works despite the bug.

$ cat Buggy.pm
sub test { "ok!" }
1;

$ perl -e'use Buggy; CORE::say(test());'
ok!

But that's just because your example is too simple. Let's add a properly-written[1] module to the mix.

$ cat Buggy.pm
sub test { "ok!" }
1;

$ cat Other.pm
package Other;
use Buggy;
1;

$ perl -e'use Other; use Buggy; CORE::say(test());'
Undefined subroutine &main::test called at -e line 1.

The bug in your module is that it doesn't have a package directive. Modules loaded using use and require must always use a package directive. But as soon as you add that, your module stops working.

$ cat NotBuggy.pm
package NotBuggy;
sub test { "ok!" }
1;

$ perl -e'use NotBuggy; CORE::say(test());'
Undefined subroutine &main::test called at -e line 1.

Exporter is used to solve that problem.

$ cat Final.pm
package Final;
use Exporter qw( import );
our @EXPORT = qw( test );
sub test { "ok!" }
1;

$ perl -e'use Final; CORE::say(test());'
ok!

  1. Well, not really. If it was properly written, it would include use use strict; use warnings 'all';. Always include that! It was omitted here to keep things visually simple.
Community
  • 1
  • 1
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • Thanks. I see the difference. But a 'library' is really what I wanted. The only reason I might want a module is if there were no other way to get a library. It's kind of bizarre to say that if I had written it properly it wouldn't work. LOL. I suppose 'pollution' is in the mind of the beholder. I don't consider having access to my own subroutines as pollution. Unnecessary complexity is pollution. – user1067305 Jul 05 '16 at 05:01
  • 1
    Pollution isn't the presence of wanted things; it's the presence of unwanted things.The problem is you have access to not just the subs you want to export, but subs that are internal to your module too. It's the sub equivalent of global variables. Programming is all about limiting scope, the exact opposite of what you said is good. Making everything global makes things harder to read, debug, maintain, etc, etc. No, this isn't a style issue. The entirety of Perl programmers stopped using these "libraries" when Perl added support for namespace support 20 years ago. – ikegami Jul 05 '16 at 05:13
  • 6
    Long story short, compartmentalizing your code requires a little extra code, but it makes the program far *less* complex. – ikegami Jul 05 '16 at 05:17
  • 2
    Maybe you should include why your second example stopped working. When using `use` or `require`, Perl only loads files once. It keeps track of what it loaded (in `%INC`). Because there's no namespace, the subs get put into the current namespace where it's loaded first. If you try to load it again, it will ignore it and only run `import` again, but since there is nothing to import, nothing happens. And then your new current namespace (`main` in this case) doesn't have the sub, and there's an _undefined_ error. – simbabque Jul 05 '16 at 07:17
  • What do you think of omitting all of the `Exporter` stuff and calling subroutines always like `Final::test()`? I ususally do so and prepend the module's name almost always because sometimes it's hard to tell (after a year) where `some_function()` came from. With `Module::some_function()` it's far easier to spot. – PerlDuck Jul 05 '16 at 11:30
  • 1
    @PerlDog; that's a lot of extra typing! Whether you use `@EXPORT` or `@EXPORT_OK`, you can always document which functions you'll be using from each module explicitly in the use line, regardless if all the subs in the module have been imported: `use Foo qw(bar baz);`. Just hop to the top of the script, and search for the function in question. Also, many editors/IDEs allow you to 'follow through' to the actual definition of the sub. – stevieb Jul 05 '16 at 13:36
  • My editor doesn't do that, but I wrote a little script that finds every sub and gives me a table of file & line for it's definition and every use. – user1067305 Jul 05 '16 at 14:31
  • @user1067305 Nice idea. But we're getting off-topic. Perhaps I'll post a question for this -- when I've figured out _where_ because it's merely opinion-based whether `Module::sub()` is better or worse than just `sub()`. – PerlDuck Jul 05 '16 at 17:23