Introducing Exporter::Almighty
Tags: perl, exporteralmighty, exportertiny
Published: 2023-03-25 17:08:59

---
title: Introducing Exporter::Almighty
published: true
date: 2023-03-25 17:02:18 UTC
tags: Perl,ExporterAlmighty,ExporterTiny,perl
canonical_url: https://toby.ink/blog/2023/03/25/introducing-exporteralmighty/
---

Consider a simple module like this:

```perl
  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:

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

[Exporter::Almighty](https://metacpan.org/pod/Exporter%3A%3AAlmighty) is a module designed to _reduce boilerplate_ in your utils-like modules, and _increase their functionality_.

The initial module can be rewritten as:

```perl
  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](https://metacpan.org/pod/Exporter%3A%3ATiny) instead of [Exporter](https://metacpan.org/pod/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:

```perl
  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:

```perl
  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:

```perl
  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:

```perl
  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:

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

They can even import a `is_Int` function:

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

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

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

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

```perl
  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](https://metacpan.org/pod/Exporter%3A%3AAlmighty). It could make things very easy for you, while adding a bunch of useful features for your caller.