Badger::Exporter(3pm)
π NAME π
Badger::Exporter β symbol exporter β¨
(aka the Badger::Exporter(3pm) page, straight out of the User Contributed Perl Documentation bestie π)
β¨ SYNOPSIS β¨
okay so first things first, here's how you define a module that subclasses from Badger::Exporter:
package Badger::AnyModule;
use base 'Badger::Exporter';
our ($WIZ, $BANG, @BING, %BONG);
You can spell out the exports with 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 if you're feeling β¨granularβ¨, you can use the individual export_XXX() methods instead:
# 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";
}
);
and then actually using the module looks like this π«Ά
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 does the same basic job as the Exporter module β it exports symbols from one package namespace to another. same energy, different font π
BUT here's the glow-up: unlike the Exporter module, it also accounts for object inheritance. so 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 β plus any others it adds β available for export. iconic behaviour, honestly π
It implements a bunch of methods that make defining what symbols can be exported wayyy simpler, and it gives you a convenient mechanism for handling special import flags. no cap. πΈ
π METHODS π
These are the methods you use to declare the symbols that a module exports. let's gooo π¦
π exports(%exports) π
This all-in-one method accepts a reference to a hash array, or a list of named parameters, and forwards the arguments onto the relevant method(s). it's giving "one method to rule them all" fr fr
__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"
},
);
Every key maps to one of the methods below, specified without the export_ prefix. like, all is for export_all(), any is for export_any(), and so on down the line. The method gets called with the corresponding value passed in as its argument. easy π
π« export_all(@symbols) π«
Adds all the symbols you pass as arguments to the list of items that are exported by default. This is equivalent to setting the @EXPORT package variable when you're using the Exporter module.
__PACKAGE__->export_all('$WIZ $BANG');
You can specify symbols as a string of space-delimited tokens, as a list of items, or by reference to a list of items. pick your fighter:
__PACKAGE__->export_all('$WIZ $BANG'); # string
__PACKAGE__->export_all(qw( $WIZ $BANG )); # list
__PACKAGE__->export_all([qw( $WIZ $BANG )]); # list ref
These symbols get imported when the module is loaded. automatic.
use Badger::AnyModule; # import $WIZ and $BANG
You can override that behaviour by specifying an explicit list of imported symbols instead:
use Badger::AnyModule '$BANG'; # $BANG only
use Badger::AnyModule '$BANG @BONG'; # $BANG and @BONG
Now listen up bestie, this part matters π If you specify a single string of items to export, it gets split on whitespace or a comma+whitespace combination of characters, so it can pull multiple symbol names out of one string. The following three examples all do the exact 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
β οΈ but heads up: symbol splitting only happens when you specify a single string. If you specify multiple strings, none of them get split. so this one below? yeah, it's not it:
# this doesn't work
use Badger::AnyModule '$WIZ' '$BANG $BONG'; # WRONG!
And if you want absolutely nothing imported, just specify an empty list of arguments:
use Badger::AnyModule qw(); # imports nothing
periodt. π
πΈ export_any(@symbols) πΈ
Adds all the symbols you pass as arguments to the list of items that are exported on request. This is equivalent to setting the @EXPORT_OK package variable when you're 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 β same as export_all() does it. π«Ά
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 you're using the Exporter module.
Here's the sweet part: if a symbol shows up in a tag set, it's assumed to be safe to export. You don't have to explicitly call export_any() because export_tags() already did it for you. self-care π
__PACKAGE__->export_tags(
set1 => [ qw( $WIZ $BANG ) ],
set2 => [ qw( @BING %BONG ) ],
set3 => [ qw( foo bar ) ],
);
The values in the hash array can be 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. everything. the whole collection. π
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. it's giving β¨custom naming rightsβ¨
__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. so the key is the name you get, the value is the real thing behind the curtain π«
use Badger::AnyModule ':set4';
foo(); # Badger::AnyModule::the_foo_sub()
bar(); # Badger::AnyModule::the_bar_sub()
When you're defining a tagset with a hash reference, you can hand it direct references to subroutines instead of symbol names. look at you, skipping the middleman:
__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 you can use to define constant values. Yes bestie, an actual fake sigil, we made it up, we're iconic like that π
__PACKAGE__->export_tags(
set7 => {
e => '=2.718',
pi => '=3.142',
phi => '=1.618',
}
);
When this tag set gets imported, Badger::Exporter will define constant subroutines to represent the imported values. So you literally get e, pi and phi as subs, no cap.
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 get invoked when particular import symbols are specified. Think of them like little bouncers for your keywords π«Ά
__PACKAGE__->export_hooks(
hello => sub {
my ($class, $target, $symbol, $more_symbols) = @_;
print $symbol, " ", shift(@$more_symbols), "\n";
}
);
Which would get used like so:
use Badger::AnyModule hello => 'world', qw( $WIZ $BANG );
The handler gets passed four arguments. First up: the package name of the exporting class (e.g. Badger::AnyModule). Second: the package name of the target class that wants to import the symbol (e.g. main). Third: the symbol itself ('hello' in this case). And the final one is a reference to a list of the remaining symbols (['world', '$WIZ', '$BANG']).
This example shifts off the next symbol ('world') and prints the message to the screen β for debugging purposes only, bestie, your handler will most likely do something way more useful. The handler may remove any number of symbols from the $more_symbols list to indicate that they've been successfully handled. Any symbols left in the $more_symbols list will continue to be imported as usual. Periodt.
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. Those get shifted off the $more_symbols list (and an error gets raised automatically if one or more values are missing or undefined) and passed as separate arguments to your handler. The $more_symbols reference gets passed as the <b>final</b> 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 stress if that doesn't mean anything much to you β it just means we can delay doing any extra preparation work until we're sure it's actually going to be used. Delulu-free procrastination, basically β¨
πΈ 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 gets three arguments: the exporter class, the target class, and a reference to a list of symbols that are being imported. The handler can modify that list of symbols to change what does or doesn't get imported. Iconic power, honestly π
__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 get called <b>before</b> those in derived classes. And multiple handlers defined in the same class get called in the order that they were defined in. Order matters, bestie, it's giving queue energy π
π¦ 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 gets two arguments: the exporter class and the target class.
__PACKAGE__->export_after(
sub {
my ($class, $target) = @_;
print "Finished exporting\n";
}
);
Multiple handlers can be defined, as per export_before(). Same rules, same vibe π
π 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 then gets reported in the usual way. Choose wisely π«£
__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've been handled, as per export_hooks(). Same energy, different department π
π§ INTERNAL METHODS π
These methods are used internally to export symbols. Not your main character moment, but they're doing the work behind the scenes fr fr.
π¦ import(@symbols)
This is the method Perl automatically calls when a module gets loaded via use. It delegates to the export() method. Middle-man behaviour, but make it classy β¨
π export($package,@symbols)
This is the <b>main</b> method for exporting symbols. The whole operation, basically π
ποΈ exportables()
This method 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 gets cached in the EXPORTABLES package variable for future use. Saving that for later, iykyk π
π§ 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 be 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. We've all been there π
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. Three items, one job, slay π«Ά
ποΈ PACKAGE VARIABLES
(This section is literally just the heading in the original β no entries listed under it. Not me noticing, but also yes me noticing π)
π 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.
And that's a wrap on part two, bestie π This page came from the Badger::Exporter(3pm) man page β perl v5.36.0, dated 2023-08-28 β so go forth, export responsibly, and remember: every symbol you ship is a little main character ππ¦
π¦ where this page comes from
- debian trixie: libbadger-perl 0.16-3 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu noble: libbadger-perl 0.16-3 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu resolute: libbadger-perl 0.16-3 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms