Consider a simple module like this:

```
package MyApp::Util::Maths;
use strict;
use warnings;
use constant PI => 3.14159265358979;
use constant EULER => 2.71828182845905;
use base 'Exporter';
our @EXPORT_OK = qw( PI EULER add );
our %EXPORT_TAGS = (
arithmetic => [qw( add )],
numbers => [qw( PI EULER )],
all => @EXPORT_OK,
);
sub add {
my ( $x, $y ) = @_;
return $x + $y;
}
1;
```

You might use it like:

```
use MyApp::Util::Maths qw( PI add );
my $pi_plus_one = add( PI, 1 );
```

Exporter::Almighty is a module designed to *reduce boilerplate* in your utils-like modules, and *increase their functionality*.

The initial module can be rewritten as:

```
package MyApp::Util::Maths;
use Exporter::Almighty -setup => {
const => {
numbers => {
PI => 3.14159265358979,
EULER => 2.71828182845905,
},
},
tag => {
arithmetic => ['add'],
},
};
sub add {
my ( $x, $y ) = @_;
return $x + $y;
}
1;
```

Exporter::Almighty sets up your exporting automatically (but using Exporter::Tiny instead of Exporter), and calls `use strict`

and `use warnings`

on your behalf.

Exporter::Almighty creates your constants for you, so you don’t need to duplicate your list of constants anywhere.

A bonus for your caller is that they can do:

```
use MyApp::Util::Maths qw( $PI $EULER );
```

To import read-only `$PI`

and `$EULER`

variables instead of traditional constants.

Your caller can also import things lexically:

```
my $pi_plus_one = do {
use MyApp::Util::Maths -lexical, qw( add $PI );
add( $PI, 1 );
};
# add() and $PI are not defined outside the above block
```

Your caller can also rename any imported functions:

```
use MyApp::Util::Maths 'add' => { -as => 'sum_of' };
```

Exporter::Almighty has integrations with Type::Tiny making it easy to define and export Type::Tiny type constraints as part of your module. For example:

```
package MyApp::Util::Maths;
use Exporter::Almighty -setup => {
const => { ... },
tag => { ... },
type => { 'Types::Standard' => ['Int', 'Num'] },
class => ['Calc' => { class => 'MyApp::Calculator' }],
};
...;
1;
```

Now people can import the **Int** and **Num** type constraints from your module:

```
use MyApp::Util::Maths qw( Int );
```

They can even import a `is_Int`

function:

```
use MyApp::Util::Maths qw( is_Int );
```

You’ve also defined a **Calc** class type constraint which can be used like this:

```
has calculator => (
is => 'ro',
isa => Calc,
default => sub { Calc->new },
);
```

Exporter::Almighty makes defining enum-like data types easy:

```
package My::Properties {
use Exporter::Almighty -setup => {
enum => { 'Status' => ['alive', 'dead', 'undead'] },
};
}
package Story::Character {
use Moo;
use My::Properties -lexical, '+Status';
use experimental 'signatures';
has status => (
is => 'ro',
isa => Status,
default => STATUS_ALIVE,
);
sub meet ( $self, $other ) {
if ( $self->status eq STATUS_ALIVE
and $other->status eq STATUS_UNDEAD ) {
print "Help!\n";
}
return $self;
}
}
```

Next time you’re writing a module that needs to export things, consider Exporter::Almighty. It could make things very easy for you, while adding a bunch of useful features for your caller.

## Top comments (0)