6

I am reading through O'Reilly's Perl Objects, References & Modules, more specifically its section about modules. It states that when using use Some::Module you can specify an import list. From its explanation it seems that the only benefit of using this list is for the sake of keeping your namespace clean. In other words, if you have a subroutine some_sub in your main package and the loaded module has a sub with the same name, your subroutine will be overridden. However, if you specify an import list and leave out some_sub from this list, you'll not have this conflict. You can then still run some_sub from the Module by declaring it like so: Some::Module::some_sub.

Is there any other benefit than the one I described above? I am asking this because in some cases you load modules with loads of functionality, even though you are only interested in some of its methods. At first I thought that by specifying an import list you only loaded those methods and not bloating memory with methods you wouldn't use anyway. However, from the explanation above that does not seem the case. Can you selectively save resources by only loading parts of a module? Or is Perl smart enough to do this when compiling without the need of a programmer's intervention?

Bram Vanroy
  • 27,032
  • 24
  • 137
  • 239
  • The import list has nothing to do with loading, it only tells how to import symbols from the module into the current package's namespace. See also [Exporter](https://metacpan.org/pod/Exporter) and the section about symbol tables in [perlmod](https://perldoc.perl.org/perlmod.html#Symbol-Tables) for more information – Håkon Hægland Apr 12 '17 at 10:36
  • It is possible to load parts of a module (but not so common), see for example [Autoloading](http://perldoc.perl.org/perlsub.html#Autoloading) in `perlsub` – Håkon Hægland Apr 12 '17 at 10:54

2 Answers2

5

From use we see that use Module LIST; means exactly

BEGIN { require Module; Module->import( LIST ); }

On the other hand, from require

Otherwise, require demands that a library file be included if it hasn't already been included. The file is included via the do-FILE mechanism, [...]

and do 'file' executes 'file' as a Perl script. Thus with use we load the whole module.

"Importing" a sub means that its name is added (or overwritten) in the caller's symbol table (via the CODE slot for the typeglob, normally aliased), by the package's import function. The sub's code isn't copied. Now, import can be written any way the author wants to, but generally the import list in the use statement merely controls what symbols are brought into the namespace. The preferred way to provide import in a module is to use the Exporter's import method.

Selective importing relieves the symbol table (and perhaps some related mechanisms), but I am not aware of practical benefits of this. The benefits are related to programming, via reduced chances for collisions.

Another clear benefit is that it nicely documents what is used in the code.

zdim
  • 64,580
  • 5
  • 52
  • 81
  • For me, this is ambiguous: *Thus with `use` we **do load the whole module**. Nevertheless, by importing only what is needed **some resources are relieved**, as some modules bring along a lot of symbols.* Considering that un-imported methods are still call-able from the module's namespace, I don't see how resources are saved. Could you clarify? – Bram Vanroy Apr 12 '17 at 09:06
  • 1
    @BramVanroy Updated, thank you for calling it. I may edit more, once I've read it tomorrow. – zdim Apr 12 '17 at 10:10
4

Note that "import list" is just a convention. Module's import function is free to do whatever it pleases with this list and you can see it (ab)used by many so-called pragma modules. Therefore partial loading is NOT bound to use in any way. For example module can load heavy function stubs WHEREVER you've imported them or not and dynamically load heavy implementation on actual first call.

Therefore use with partial import list may, or may not actually save any resources - it is all depends on actual implementation of used module.

While require and use indeed load entire .pm file - that file well could be just a lightweight stub and loader for actual code located elsewhere. There's another convention to call those modules ::Heavy.

Modules are free to implement partial loading in any way they please as well. Here are just some possibilities how module can save resources:

  1. AUTOLOAD (with its complimentary AutoLoader, AutoSplit, and SelfLoader modules).
  2. Use stubs that load necessary submodules.
  3. Dynamically load heavy data (i.e. dictionaries or encoding maps) when they are first accessed by their name.
  4. If you depend on other heavy modules, dynamically require them at runtime in functions that depend on them instead of compile-time use at the very start.

Everything on this list could work automatically behind the scenes, exposed through use import list, or work/be called in other, completely arbitrary way. Once again, it's completely up to module's implementation.

Oleg V. Volkov
  • 21,719
  • 4
  • 44
  • 68
  • So if I understand correctly, it all depends on the implementation of the module, as there is no 'standard best practice' for building modules. One would expect that this was optimized, in a way, such that loading modules is as efficient as possible; or am I wrong? – Bram Vanroy Apr 12 '17 at 11:57
  • Pretty much - yes. Check the AUTOLOAD link - it does have some automation tools. But you can't just optimize everything automatically. For example `Encoding` module have pretty heavy code for CJK languages and then even more heavy codepoint maps for each of them. Automated tool can't understand intent of your code, so it's up to author to dynamically load common CJK code and specific maps when they're required by algorithm. It's like that everywhere in optimization. Optimizing compiler will do lots of cool low-level tricks, but it won't replace your bubble sort with something better. – Oleg V. Volkov Apr 12 '17 at 12:12