Provided by: libbadger-perl_0.16-3_all bug

NAME

       Badger::Exporter - symbol exporter

SYNOPSIS

       Defining a module subclassed from Badger::Exporter:

           package Badger::AnyModule;
           use base 'Badger::Exporter';
           our ($WIZ, $BANG, @BING, %BONG);

       Specifying the exports using the all-in-one "exports()" method:

           __PACKAGE__->exports(
               all  => '$WIZ $BANG',           # like Exporter's @EXPORT
               any  => '@BING %BONG',          # like @EXPORT_OK
               tags => {                       # like %EXPORT_TAGS
                   foobar => 'foo bar',
               },
               hooks => {                      # custom hooks
                   hello => sub {
                       print "Hello World!\n"
                   },
               },
               fail => sub {                   # handle unknown exports
                   print "I'm sorry Dave, I can't do that.\n"
               },
               before => sub {                 # pre-import hook
                   my ($class, $target, $symbols) = @_;
                   print "This gets run before the import\n"
               },
               after => sub {                 # post-import hook
                   my ($class, $target) = @_;
                   print "This gets run after the import\n"
               },
           );

       Or individual "export_XXX()" methods:

           # export all these symbols by default       # methods can take either
           __PACKAGE__->export_all(qw( $WIZ $BANG ));  # a list of symbols or a
           __PACKAGE__->export_all('$WIZ $BANG');      # space-delimited string

           # export these symbols if requested
           __PACKAGE__->export_any(qw( @BING %BONG )); # list
           __PACKAGE__->export_any('@BING %BONG');     # string

           # define sets of symbols for export
           __PACKAGE__->export_tags(
               set1 => [ qw( $WIZ $BANG ) ],           # list
               set2 => '@BING %BONG',                  # string
               set3 => 'foo bar',                      # string
               set4 => {                               # hash
                   # use hash ref to define aliases for symbols
                   foo => '&the_foo_sub',
                   bar => '&the_bar_sub',
               },
           );

           # define hooks for import symbols
           __PACKAGE__->export_hooks(
               hello => sub {
                   my ($class, $target, $symbol, $more_symbols) = @_;
                   print $symbol, " ", shift(@$more_symbols), "\n";
               }
           );

           # define generic hooks to run before/after import
           __PACKAGE__->export_before(
               sub {
                   my ($class, $target, $symbols) = @_;
                   print "This gets run before the import\n"
               }
           );
           __PACKAGE__->export_after(
               sub {
                   my ($class, $target) = @_;
                   print "This gets run after the import\n"
               }
           );

           # define catch-all for any failed import symbols
           __PACKAGE__->export_fail(
               sub {
                   my ($class, $target, $symbol, $more_symbols) = @_;
                   warn "Cannot export $symbol from $class to $target\n";
               }
           );

       Using the module:

           package main;

           # imports default items: $WIZ $BANG
           use Badger::AnyModule;

           # import specific items
           use Badger::AnyModule qw( $WIZ @BING );

           # import user-defined sets
           use Badger::AnyModule qw( :set1 :set3 );

           # specifying the :default set ($WIZ $BANG) and others
           use Badger::AnyModule qw( :default @BING );

           # importing all symbols using the :all set
           use Badger::AnyModule ':all';

           # specifying multiple symbols in a single string
           use Badger::AnyModule ':set1 $WIZ @BING';

           # triggering import hooks: prints "hello world\n";
           use Badger::AnyModule
               hello => 'world';

           # import hooks and other items
           use Badger::AnyModule
               hello => 'world',
               qw( @BING %BONG );

           # import fail hook gets called for any unknown symbols
           use Badger::AnyModule 'badger';
               # warns: Cannot export badger from Badger::AnyModule to main

           # imports indicates that all remaining arguments are symbols to
           # import, bypassing any hooks
           use Badger::AnyModule
               hello   => 'world'
               imports => qw( @BING %BONG );

           # import (singular) option indicates that the next item is an
           # import symbols (or multiple symbols in a single string) and
           # disables hooks for that item only.
           use Badger::AnyModule
               import => '@BING %BONG';

DESCRIPTION

       This module performs the same basic function as the "Exporter" module in that it exports symbols from one
       package namespace to another.

       Howevever, unlike the "Exporter" module it also accounts for object inheritance. If your base class
       module defines a set of exportable symbols then any subclasses derived from it will also have that same
       set of symbols (and any others it adds) available for export.

       It implements a number of methods that simplify the process of defining what symbols can be exported, and
       provides a convenient mechanism for handling special import flags.

METHODS

       These methods can be used to declare the symbols that a module exports.

   exports(%exports)
       This all-in-one methods accepts a reference to a hash array, or a list of named parameters and forwards
       the arguments onto the relevant method(s).

           __PACKAGE__->exports(
               all  => '$WIZ $BANG',           # like Exporter's @EXPORT
               any  => '@BING %BONG',          # like @EXPORT_OK
               tags => {                       # like %EXPORT_TAGS
                   foobar => 'foo bar',
               },
               hooks => {                      # custom hooks
                   hello => sub {
                       print "Hello World!\n"
                   },
               },
               fail => sub {                   # handle unknown exports
                   print "I'm sorry Dave, I can't do that.\n"
               },
           );

       Each key corresponds to one of the methods below, specified without the "export_" prefix. e.g. "all" for
       export_all(), "any" for export_any() and so on. The method is called with the corresponding value being
       passed as an argument.

   export_all(@symbols)
       Adds all the symbols passed as arguments to the list of items that are exported by default.  This is
       equivalent to setting the @EXPORT package variable when using the "Exporter" module.

           __PACKAGE__->export_all('$WIZ $BANG');

       Symbols can be specified as a a string of space-delimited tokens, as a list of items, or by reference to
       a list of items.

           __PACKAGE__->export_all('$WIZ $BANG');          # string
           __PACKAGE__->export_all(qw( $WIZ $BANG ));      # list
           __PACKAGE__->export_all([qw( $WIZ $BANG )]);    # list ref

       These symbols will be imported when the module is loaded.

           use Badger::AnyModule;                  # import $WIZ and $BANG

       This behaviour can be overridden by specifying an explicit list of imported symbols.

           use Badger::AnyModule '$BANG';          # $BANG only
           use Badger::AnyModule '$BANG @BONG';    # $BANG and @BONG

       If you specify a single string of items to export then it will be split on whitespace or a
       comma+whitespace combination of characters to extract multiple symbol names from the string.  The
       following three examples all do the same thing.  The last two are effectively identical in all but
       syntax.

           use Badger::AnyModule '$BANG @BONG';    # single string
           use Badger::AnyModule '$BANG' '@BONG';  # two strings
           use Badger::AnyModule qw($BANG @BONG);  # same as above

       Note that symbol splitting occurs when you specify a single string.  If you specify multiple strings then
       none are split.

           # this doesn't work
           use Badger::AnyModule '$WIZ' '$BANG $BONG';     # WRONG!

       Specify an empty list of arguments if you don't want any symbols imported.

           use Badger::AnyModule qw();             # imports nothing

   export_any(@symbols)
       Adds all the symbols passed as arguments to the list of items that are exported on request. This is
       equivalent to setting the @EXPORT_OK package variable when using the "Exporter" module.

           __PACKAGE__->export_any(qw( $WIZ $BANG ));

       Symbols can be specified as a space-delimited string, a list, or by reference to a list, as per
       export_all().

       The symbols specified as arguments are imported when the module is loaded.

           use Badger::AnyModule '$BANG';          # $BANG only
           use Badger::AnyModule '$BANG @BONG';    # $BANG and @BONG
           use Badger::AnyModule qw($BANG @BONG);  # $BANG and @BONG

   export_tags(%tagsets)
       Define one or more sets of symbols.  This is equivalent to setting the %EXPORT_TAGS package variable when
       using the "Exporter" module.

       If a symbol appears in a tag set then it is assumed to be safe to export. You don't need to explicitly
       call export_any() because the export_tags() method does it for you.

           __PACKAGE__->export_tags(
               set1 => [ qw( $WIZ $BANG ) ],
               set2 => [ qw( @BING %BONG ) ],
               set3 => [ qw( foo bar ) ],
           );

       The values in the hash array can be specified as references to lists, or space-delimited strings.

           __PACKAGE__->export_tags(
               set1 => '$WIZ $BANG',
               set2 => '@BING %BONG',
               set3 => 'foo bar',
           );

       To load a set of symbols, specify the tag name with a '":"' prefix.

           use Badger::AnyModule ':set1';
           use Badger::AnyModule ':set1 :set2';
           use Badger::AnyModule qw(:set1 :set2);

       The special '":all"' set imports all symbols.

           use Badger::AnyModule ':all';

       The special '":default"' set imports the default set of symbols.

           use Badger::AnyModule ':default @BONG';

       You can also use the "export_tags()" method to define a hash array mapping aliases to symbols.

           __PACKAGE__->export_tags(
               set4 => {
                   # use hash ref to define aliases for symbols
                   foo => '&the_foo_sub',
                   bar => '&the_bar_sub',
               }
           );

       When this tagset is imported, the symbols identified by the values in the hash reference (&the_foo_sub
       and &the_bar_sub) are exported into the caller's package as the symbols named in the corresponding keys.

           use Badger::AnyModule ':set4';

           foo();    # Badger::AnyModule::the_foo_sub()
           bar();    # Badger::AnyModule::the_bar_sub()

       When defining a tagset with a hash reference, you can provide direct references to subroutines instead of
       symbol names.

           __PACKAGE__->export_tags(
               set5 => {
                   # use hash ref to define aliases for subroutines
                   foo => \&the_foo_sub,
                   bar => \&the_bar_sub,
               }
           );

       You can also explicitly specify the package name for a symbol:

           __PACKAGE__->export_tags(
               set6 => {
                   foo  => 'Badger::Example::One::foo',
                   bar  => '&Badger:Example::One::bar',
                   '$X' => '$Badger::Example::Two:X',
                   '$Y' => '$Badger::Example::Two:Y',
               }
           );

       The "Badger::Exporter" module also recognises the "=" pseudo-sigil which can be used to define constant
       values.

           __PACKAGE__->export_tags(
               set7 => {
                   e   => '=2.718',
                   pi  => '=3.142',
                   phi => '=1.618',
               }
           );

       When this tag set is imported, "Badger::Exporter" will define constant subroutines to represent the
       imported values.

           use Badger::AnyModule ':set7';

           print e;            # 2.718
           print pi;           # 3.142
           print phi;          # 1.618

   export_hooks(%hooks)
       Defines one or more handlers that are invoked when particular import symbols are specified.

           __PACKAGE__->export_hooks(
               hello => sub {
                   my ($class, $target, $symbol, $more_symbols) = @_;
                   print $symbol, " ", shift(@$more_symbols), "\n";
               }
           );

       This would be used like so:

           use Badger::AnyModule hello => 'world', qw( $WIZ $BANG );

       The handler is passed four arguments. The first is the package name of the exporting class (e.g.
       "Badger::AnyModule"). The second argument is the package name of the target class which wants to import
       the symbol (e.g.  "main"). The symbol itself ('"hello"' in this case) is passed as the third argument.
       The final argument is a reference to a list of remaining symbols ("['world', '$WIZ', '$BANG']").

       This example shifts off the next symbol ('"world"') and prints the message to the screen (for debugging
       purposes only - your handler will most likely do something more useful).  The handler may remove any
       number of symbols from the $more_symbols list to indicate that they have been successfully handled.  Any
       symbols left in the $more_symbols list will continue to be imported as usual.

       You can also define export hooks as an array reference. The code reference should be the first item in
       the array. The second item is the number of arguments it expects. These will be shifted off the
       $more_symbols list (automatically raising an error if one or more values are missing or undefined) and
       passed as separate arguments to your handler. The $more_symbols reference will be passed as the final
       argument.

           __PACKAGE__->export_hooks(
               example => [ \&my_export_hook, 2 ],
           );

           sub my_export_hook {
               my ($self, $target, $symbol, $arg1, $arg2, $more_symbols) = @_;
               # your code...
           }

       Hooks expressed this way will have closures created around them on demand by the export_hook_generator()
       method.  Don't worry if that doesn't mean anything much to you.  It simply means that we can delay doing
       any extra preparation work until we're sure that it's going to be used.

   export_before(\&handler)
       This method can be called to register a handler that will be called immediately before the exporter
       starts importing symbols.  The handler is passed three arguments: the exporter class, the target class,
       and a reference to a list of symbols that are being imported.  The handler can modify the list of symbols
       to change what does or doesn't get imported.

           __PACKAGE__->export_before(
               sub {
                   my ($class, $target, $symbols) = @_;
                   print "About to import symbols: ", join(', ', @$symbols), "\n";
               }
           );

       Multiple handlers can be defined, either in the same class or inherited from base classes.  Handlers
       defined in base classes are called before those in derived classes.  Multiple handlers defined in the
       same class will be called in the order that they were defined in.

   export_after(\&handler)
       This method can be called to register a handler that will be called immediately after the exporter has
       finished importing symbols.  The handler is passed two arguments: the exporter class and target class.

           __PACKAGE__->export_after(
               sub {
                   my ($class, $target) = @_;
                   print "Finished exporting\n";
               }
           );

       Multiple handlers can be defined, as per export_before().

   export_fail(\&handler)
       This method can be used to register a subroutine to handle any export failures. The arguments passed are
       as per export_hooks(). The method should return 1 to indicate that the symbol was handled without error,
       or 0 to indicate failure which is then reported in the usual way.

           __PACKAGE__->export_fail(
               sub {
                   my ($class, $target, $symbol, $more_symbols) = @_;
                   if ($symbol eq 'badger') {
                       print "OK, we'll let you import a badger\n";
                       return 1;
                   }
                   else {
                       print "You cannot import $symbol from $class into $target\n";
                       return 0;
                   }
               }
           );

       An "export_fail" handler may also remove symbols from the $more_symbols list to indicate that they have
       been handled, as per "export_hooks()".

INTERNAL METHODS

       These methods are used internally to export symbols.

   import(@symbols)
       This is the method automatically called by Perl when a module is loaded via "use".  It delegates to the
       export() method.

   export($package,@symbols)
       This is the main method for exporting symbols.

   exportables()
       This methods collects and collates the values of the various package variables that control the exporter
       ("EXPORT_ALL", "EXPORT_ANY", etc).  It returns a reference to an array containing:

           [\@all, \%any, \%tags, \%hooks, \@fails];

       This array reference is cached in the "EXPORTABLES" package variable for future use.

   export_symbol($package,$symbol,$coderef)
       This method can be used to install a code reference as a symbol in a package.

           Badger::Exporter->export_symbol('My::Package', 'Foo', \&foosub);

   export_hook_generator($name,\&code,$nargs)
       This method is used to generate a closure (a fancy way of saying "wrapper subroutine") around an existing
       export hook subroutine.  Bare naked export hooks are typically written like this:

           sub code {
               my ($self, $target, $symbol, $more_symbols) = @_
               # your code...
           }

       Your code is responsible for shifting any arguments it expects off the front of the $more_symbols list.
       It should also being doing all the messy stuff like making sure the $more_symbols list contains enough
       arguments and that they're all set to defined values.  But I bet you forget sometimes, don't you?  That's
       OK, it's easily done.

       The purpose of the "export_hook_generator()" method is to simplify argument processing so that hooks can
       be specified as:

           [\&my_code, $nargs]

       and written as:

           sub code {
               my (
                   $self, $target, $symbol,    # the usual first three items
                   $arg1, $arg2, ..., $argn,   # your $nargs items
                   $more_symbols               # the remaining items
               ) = @_
           }

       The method should be called like something like this:

           my $hook = Badger::Exporter->export_hook_generator(
               'wibble', \&code, 2
           );

       The first argument should be the name of the option that the hook is being generated for.  This is used
       to report any argument errors, e.g.

           Missing value for the 'wibble' option (2 wanted, 1 available)

       Or:

           Missing value for the 'wibble' option (argument 2 of 2 is undefined)

       The second argument is a reference to your handler subroutine.  The third argument is the number of
       additional arguments your subroutine expects.

PACKAGE VARIABLES

AUTHOR

       Andy Wardley <http://wardley.org/>

COPYRIGHT

       Copyright (C) 1996-2009 Andy Wardley.  All Rights Reserved.

       This module is free software; you can redistribute it and/or modify it under the same terms as Perl
       itself.

perl v5.36.0                                       2023-08-28                              Badger::Exporter(3pm)