1

For example, if there are the following modules, I would like to import:

  • My::Plugin::FeatureA
  • My::Plugin::FeatureB
  • My::Plugin::AnotherFeature

I do this:

use My::Plugin::FeatureA;
use My::Plugin::FeatureB;
use My::Plugin::AnotherFeature;

Is there a module to combine these statements? ie given a prefix and name list similar in style to this:

use IMPORTER qw<My::Plugin FeatureA FeatureB AnotherFeature>;

This example doesn't account for non default symbols being exported, but am curious if something like this exists, or if it should be created.

Plack::Builder has the builder subroutine for middleware/plugings, which is kind of the style I'm after. However the idea would be to use it as a pragma.

toolic
  • 57,801
  • 17
  • 75
  • 117
drclaw
  • 2,463
  • 9
  • 23
  • 1
    I suggest to rework the quesiton so that it is more specific and not about software recommendation. I think it's a worthy question to ask (and get answers to) – zdim Apr 27 '23 at 06:01
  • The posts linked in closing this question are NOT good answers, certainly not definitive. The second one is a long listing of posts, which I went through when it was posted as a comment, which has *one* proper answer buried somewhere, and that one has iffy parts as well. (Others are ruminations or software recommendations, with no comments or examples. Useful but no solution.) What I mean is that this should've not been closed as a dupe, or we should find good answers to this legitimate question. I couldn't complain if it were closed as "off topic" though (seeking software recommendations). – zdim Apr 27 '23 at 19:10

1 Answers1

3

I take the question to ask 'how can I combine import statements', and that it says how it tried to write a module to implement the desired import statement they show but how they ran into subtle problems. (They must've misspoken so that this looks like a quest of software recommendations, and they're about to edit the question and correct that impression.)

At any rate, the desired import/pragma statement shown in the question strikes me as impossible -- for one, how to accommodate import lists that of course may differ across these modules? Once we are at it, what about pragmas? Etc.

Writing a module that assembles import statements is indeed actually tricky as one can't just pile up those import statements. But it can be done and they've done it -- see Import::Into.

From synopsis

package My::MultiExporter;

use Import::Into;

sub import {
  my $target = caller;
  Thing1->import::into($target);
  Thing2->import::into($target, qw(import arguments));
}

# etc -- there's way, way more

Then you use My::MultiExporter; in your program(s).


Here's a sketch for something perhaps more to the point, assembling sets of modules

package LoadModules;

use warnings;
use strict;
use feature 'say';

use Import::Into;

# Initializing this hash to all supported keys also serves as documentation
my %arg = map { $_ => '' } qw(base utils extras file all); #etc

sub import
{
    my ($pack, @args) = @_;

    %arg = map { $_ => 1 } @args;

    my $target = caller;

    warnings ->import::into($target);
    strict   ->import::into($target);
    feature  ->import::into($target, ':5.10');

    if ($arg{base}) {
        Getopt::Long ->import::into($target);
        Const::Fast  ->import::into($target);
        Data::Dump   ->import::into($target, qw(dd pp));
    }
    
    if ($arg{utils}) {
        List::Util      ->import::into($target, qw(min max));
        List::MoreUtils ->import::into($target, qw(any all none uniq));
    }

    # ... etc ...
}

1;

Then we'd load wanted bundles as use LoadModules qw(base utils); etc.

To take it further, have subs load bundles so that options can be combined without code repetition

sub import {
   ...

   _load_base($target)  if $arg{base};
   _load_utils($target) if $arg{utils};

   if ($arg{all}) { 
      _load_base($target);
      _load_utils($target);
      ...
   }
}

sub _load_base {
    my ($target) = @_;
    Getopt::Long ->import::into($target);
    Const::Fast  ->import::into($target);
    Data::Dump   ->import::into($target, qw(dd pp));
}
...

There are of course other ways to organize arguments; or just automate their processing by loading them via a dispatch table.

This approach lacks a listing of imported symbols in the program, but that is the ever present puzzle of how to best both simplify import statements and yet have imports documented.

The code above is a sketch that needs work but hopefully it is useful.

Another option is to have a separate import-by-bundle files for varying sets of options, or to combine it (multiple packages but some of them with multiple options, including similar bundles).

zdim
  • 64,580
  • 5
  • 52
  • 81