How to include all / some of the "helper modules" in a Perl script?

I’m just starting out by saying that I’m not at all tested when creating Perl modules, so I’m sorry if I am leaving here.

Let's say I create several modules:

foo::bar foo::bar::a foo::bar::b 

Since I don’t know what they are called, I call the sub.pm and b.pm modules “auxiliary modules” because they are associated with the bar.pm module, but can be somewhat independent.

So one of my Perl scripts could use foo :: bar :: a, another script could use foo :: bar :: b, and maybe I have another script that should use functions from "a" and "b". Instead of this:

 use foo::bar; use foo::bar::a qw(one two); use foo::bar::b; 

I want to do something like this:

 use foo::bar qw(:a :b); 

In my opinion, this will give my script access to everyone in bar.pm, a.pm and b.pm.

I checked something like this and I was clearly wrong.

Is something like this possible? I suppose I could use bar.pm a.pm and b.pm and then have wrapper functions that pass the call to the helper modules, but it seems like there will be an easier way.

+4
source share
6 answers

Take a look at my Test :: Data for an example of this. Despite the fact that you can do this, I have never experienced a terrifying result. Instead, you might consider the Plugin or Mixin approach. There are several modules on CPAN that can help with this.

Here's the custom import I wrote for Test :: Data:

  sub import 
     {
     my $ self = shift;
     my $ caller = caller;

     foreach my $ package (@_)
         {
         my $ full_package = "Test :: Data :: $ package";
         eval "require $ full_package; 1";
         if ( $@ )
             {
             carp "Could not require Test :: Data :: $ package: $@ ";
             }

         $ full_package-> export ($ caller);
         }

     }
+5
source

Yes you can do it. This is probably due to writing a custom "helper import" in foo :: bar, which interprets the incoming arguments the way you want.

You are probably using Exporter right now, and this lack of support for your syntax is the problem. You will find that nothing special has been implemented in the syntax of the Exporter module; it is just a general convention. You will most likely want to see how the business does this in order to get an idea of ​​how you want.

+2
source

If you do not know which module is being called, why do you enable it? You do not need to enable it. Include only the module in the (calling) module that it needs, and nowhere else.

That is: if you use it, then use it. If you are not using it, do not use it.

+1
source

Also try looking Class :: MixinFactory

0
source

Yes, but you need to configure your own import:

 use strict; use warnings; package ab; use base qw<Exporter>; our @EXPORT_OK; our %EXPORT_TAGS; BEGIN { @EXPORT_OK = qw<>; %EXPORT_TAGS = ( a => 1, b => 1, all => \@EXPORT_OK ); } sub setup_part { #use Smart::Comments; my $code = shift; my $mini_path = "foo/bar/$code.pm"; return if exists $INC{$mini_path}; require $mini_path; my $arr_ref = do { no strict 'refs'; \@{Symbol::qualify( 'EXPORT_OK', $code )}; }; $code->import( @$arr_ref ); push @EXPORT_OK, @$arr_ref; $EXPORT_TAGS{$code} = [ @$arr_ref ]; return; } sub import { my ( $package_name, @imports ) = @_; my %import_hash = map { $_ => 1 } @imports; if ( exists $import_hash{':all'} ) { @import_hash{qw<:a :b>} = ( 1, 1 ); } foreach my $import ( grep { exists $import_hash{$_} } qw<:a :b> ) { setup_part( substr( $import, 1 )); } goto &{Exporter->can( 'import' )}; } 1; 
0
source

I was looking for a solution similar to the recent one. I know the thread is too old, but I would like to comment on the answer (February 12, at 17:55) brian d foy , but, unfortunately, I do not have enough reputation to accomplish this. Therefore, I am adding my comment as a new answer.

His answer helped me solve a recent problem. But this requires some modification if used with use lib .

I have a bunch of modules that look like A::B::* . They must be loaded in scripts by the general module A::B All of these modules are located within their files in the same directory as when loading the script. Using the mechanism suggested by brian d foy , we can get many overridden subroutine errors. To avoid all of them, I believe that I have found a better solution, better than no warnings 'redefine' . Now we can use use lib , no warnings 'redefine' or shift @INC, ... in the main script.

     sub import {
         @TAGS = (@_);
         my $ me = shift @TAGS;

         (my $ pm = $ me) = ~ s | :: | / | g;
         $ pm. = ".pm";

         ($ dir = $ INC {$ pm}) = ~ s / \. pm $ //;
         foreach (glob "$ dir / *. pm") {
             /(\w+)\.pm$/;
             my $ module = "$ {me} :: $ 1";

             eval "use $ module qw (: all)";  # You are free to use any items in the exporting list
             die "$ me: Error while loading $ module from $ _: $@ \ n" if $@ ;
         }

         # Fill in @EXPORT_OK and% EXPORT_TAGS manually from each A :: B :: * :: EXPORT_OK
         # ...

         goto & {Exporter-> can ("import")};
     }

0
source

All Articles