NAME
   Constant::Export::Lazy - Utility to write lazy exporters of constant
   subroutines

DESCRIPTION
   This is a utility to write lazy exporters of constant subroutines. I.e.
   it's not meant to be a user-facing constant exporting API, it's meant to
   write user-facing constant exporting APIs.

   There's dozens of similar constant defining modules on the CPAN, why did
   I need to write this one?

   *   It's lazy

       Our constants fleshened via callbacks that are guaranteed to be
       called only once for the lifetime of the process (not once per
       importer or whatever), and we only call the callbacks lazily if
       someone actually requests that a constant of ours be defined.

       This makes it easy to have one file that runs in different
       environments and e.g. generates some subset of its constants with a
       module that you may not want to use, or may not be available in all
       your environments. You can just "require" it in the callback that
       generates the constant that requires it.

   *   It makes it easier to manage creating constants that require other
       constants

       Maybe you have one constant indicating whether you're running in a
       dev environment, and a bunch of other constants that are defined
       differently if the dev environment constant is true.

       Now imagine you have several hundred constants like that, managing
       the inter-dependencies and that everything is defined in the right
       order quickly gets messy.

       Constant::Import::Lazy takes away all this complexity. When you
       define a constant you get a callback object that can give you the
       value of other constants, and will either generate them if they
       haven't been generated, or look them up in the symbol table if they
       have.

       Thus we end up with a Makefile-like system where you can freely use
       whatever other constants you like when defining your constants, just
       be careful not to introduce circular dependencies.

SYNOPSIS
   So how does all this work? This example demonstrates all our features.
   This is an example of your "My::Constants" package that you write using
   "Constant::Export::Lazy":

       package My::Constants;
       use strict;
       use warnings;
       use Exporter 'import';
       use constant {
           X => -2,
           Y => -1,
       };
       our @EXPORT_OK = qw(X Y);
       use Constant::Export::Lazy (
           constants => {
               A => sub { 1 },
               B => sub { 2 },
               SUM => sub {
                   # You get a $ctx object that you can ->call() to retrieve
                   # the values of other constants if some of your constants
                   # depend on others. Constants are still guaranteed to only
                   # be fleshened once!
                   my ($ctx) = @_;
                   $ctx->call('A') + $ctx->call('B'),
               },
               # We won't call this and die unless someone requests it when
               # they import us.
               DIE => sub { die },
               PI  => {
                   # We can also supply a HashRef with "call" with the sub,
                   # and "options" with options that clobber the global
                   # options.
                   call    => sub { 3.14 },
                   options => {
                       override => sub {
                           my ($ctx, $name) = @_;
                           # You can simply "return;" here to say "I don't
                           # want to override", and "return undef;" if you
                           # want the constant to be undef.
                           return $ENV{PI} ? "Pi is = $ENV{PI}" : $ctx->call($name);
                       },
                   },
               },
           },
           options => {
               # We're still exporting some legacy constants via Exporter.pm
               wrap_existing_import => 1,
               # A general override so you can override other constants in
               # %ENV
               override => sub {
                   my ($ctx, $name) = @_;
                   return unless exists $ENV{$name};
                   return $ENV{$name};
               },
           },
       );

       1;

   And this is an example of using it in some user code:

       package My::User::Code;
       use strict;
       use warnings;
       use Test::More qw(no_plan);
       use lib 't/lib';
       BEGIN {
           # Supply a more accurate PI
           $ENV{PI} = 3.14159;
           # Override B
           $ENV{B} = 3;
       }
       use My::Constants qw(
           X
           Y
           A
           B
           SUM
           PI
       );

       is(X, -2);
       is(Y, -1);
       is(A, 1);
       is(B, 3);
       is(SUM, 4);
       is(PI,  "Pi is = 3.14159");

   Things to note about this example:

   *   We're using "$ctx-"call($name)> to get the value of other constants
       while defining ours.

   *   That you can use either a global "override" option or a local
       per-sub one to override your constants via %ENV variables, or
       anything else you can think of.

   *   We're using the global "wrap_existing_import" option, and Exporter
       to export some of our constants via constant.

       This demonstrates migrating an existing module that takes a list of
       constants (or labels) that don't overlap with our list of constants
       to "Constant::Export::Lazy".

       As well as supplying this option you have to "use
       Constant::Export::Lazy" after the other module defines its "import"
       subroutine. Then we basically compose a list of constants we know we
       can handle, and dispatch anything we don't know about to the
       "import" subroutine we clobbered.

AUTHOR
   Ævar Arnfjörð Bjarmason <[email protected]>