12

I want use some packages and some pragmas in all my programs, like:

use 5.014;
use warnings;
use autodie;
use My::ModuleA::Something;
use ModuleB qw(Func1 Func2);

I don't want repeat myself in every module, so looking for a way how to make one package e.g. My::Common what will contain the above packages and in my programs do only:

use My::Common;
say Func1("hello"); #say enabled and Func1 imported in the My::Common

how to achieve this?

The was read preldoc -f use and perldoc perlmodlib so i think I must "somewhat" to do this with BEGIN plus require&import, but absolutely don't know how.


UPDATE: I'm already tried the basic things.

With require - my prg.pl program.

require 'mymods.pl';
$var = "hello";
croak "$var\n";

mymods.pl contain

use strict;
use feature 'say';
use Carp qw(carp croak cluck);
1;

DOES NOT WORKS. Got error:

$ perl prg.pl 
String found where operator expected at prg.pl line 3, near "croak "$var\n""
    (Do you need to predeclare croak?)
syntax error at prg.pl line 3, near "croak "$var\n""
Execution of prg.pl aborted due to compilation errors.

with "use My":

use My;
$var = "hello";
croak "$var\n";

my My.pm

package My;
use strict;
use feature 'say';
use Carp qw(carp croak cluck);
1;

DOES NOT WORKS either. Got the same error.


Any working idea?

matthias krull
  • 4,389
  • 3
  • 34
  • 54
kobame
  • 5,766
  • 3
  • 31
  • 62

3 Answers3

8

I'd go with this:

package My::Common;
use 5.14.0;
use strict;
use warnings;
use autodie;
use Carp qw(carp croak cluck);

sub import {
    my $caller = caller;
    feature->import(':5.14');
    # feature->import('say');
    strict->import;
    warnings->import;
    ## autodie->import; # <-- Won't affect the caller side - see my edit.
    {
        no strict 'refs';
        for my $method (qw/carp croak cluck/) {
            *{"$caller\::$method"} = __PACKAGE__->can($method);
        }
    }
}

1;

Please correct me if I'm wrong, or there's a better way.


EDIT:

Sorry, I was wrong in using autodie->import...

This one should work, but it assumes that you always call My::Common from the main package:

package My::Common;
# ...
sub import {
    # ...
    strict->import;
    warnings->import;
    {
        package main;
        autodie->import;
    }
    # ...
}

So, of course, it's much safer and simpler to add a use autodie; to each script:

use My::Common;
use autodie;
# ...
yibe
  • 3,939
  • 2
  • 24
  • 17
  • YES! This works. ;) Thanx. So, need call import, and for the exported functions need do the dark VooDoo :) with *{"$caller....}. – kobame Jun 27 '11 at 12:18
  • @kobame: Oh wait, I just found out that `autodie->import` didn't work as I thought it would. Please take a look at my edit. – yibe Jun 27 '11 at 15:08
  • 2
    Why no mention of prior art on CPAN? [Toolkit](http://p3rl.org/Toolkit), [ToolSet](http://p3rl.org/ToolSet), [rig](http://p3rl.org/rig), [perl5i](http://p3rl.org/perl5i), [perl5](http://p3rl.org/perl5) do this already. – daxim Jun 27 '11 at 16:45
  • See [How can I export a list of modules with my own module?](http://stackoverflow.com/questions/30814892/how-can-i-export-a-list-of-modules-with-my-own-module) for an overview of CPAN modules. – Håkon Hægland Aug 15 '16 at 13:54
8

It's actually fairly simple, if you override your "common" module's import method. See the source of chromatic's Modern::Perl module for an example of exporting pragmas.

For re-exporting things defined in other modules, I seem to recall that $export_to_level (see the Exporter docs, although it's not explained all that clearly) should do that, although I can't find any good examples at the moment. Another option would be Pollute::persistent, although I haven't used it, don't know anyone else who's used it, and can't say how stable/solid it's likely to be. If it works, though, it's probably the quickest and easiest option.

xxfelixxx
  • 6,512
  • 3
  • 31
  • 38
Dave Sherohman
  • 45,363
  • 14
  • 64
  • 102
3

I've just noticed a module called rig in CPAN. Try it out.

Rob Hruska
  • 118,520
  • 32
  • 167
  • 192
Baggio
  • 31
  • 1