This is an automated email from the git hooks/post-receive script. js pushed a commit to tag 0.043_01 in repository libexporter-tiny-perl.
commit 3dc479d304b5de655d3de436e7571c27f9ad6f72 Author: Toby Inkster <m...@tobyinkster.co.uk> Date: Sun Nov 9 00:25:47 2014 +0000 major documentation restructure --- lib/Exporter/Shiny.pm | 7 +- lib/Exporter/Tiny.pm | 416 ++------------------------------- lib/Exporter/Tiny/Manual/Etc.pm | 134 +++++++++++ lib/Exporter/Tiny/Manual/Exporting.pm | 256 ++++++++++++++++++++ lib/Exporter/Tiny/Manual/Importing.pm | 253 ++++++++++++++++++++ lib/Exporter/Tiny/Manual/QuickStart.pm | 195 ++++++++++++++++ 6 files changed, 858 insertions(+), 403 deletions(-) diff --git a/lib/Exporter/Shiny.pm b/lib/Exporter/Shiny.pm index 063cb47..016ff93 100644 --- a/lib/Exporter/Shiny.pm +++ b/lib/Exporter/Shiny.pm @@ -90,7 +90,12 @@ L<http://rt.cpan.org/Dist/Display.html?Queue=Exporter-Tiny>. =head1 SEE ALSO -L<Exporter::Tiny>. +This module is just a wrapper around L<Exporter::Tiny>, so take a look +at L<Exporter::Tiny::Manual::QuickStart> and +L<Exporter::Tiny::Manual::Exporting> for further information on what +features are available. + +Other interesting exporters: L<Sub::Exporter>, L<Exporter>. =head1 AUTHOR diff --git a/lib/Exporter/Tiny.pm b/lib/Exporter/Tiny.pm index 5e437da..fcfc457 100644 --- a/lib/Exporter/Tiny.pm +++ b/lib/Exporter/Tiny.pm @@ -371,7 +371,7 @@ Exporter::Tiny - an exporter with the features of Sub::Exporter but only core de package MyUtils; use base "Exporter::Tiny"; our @EXPORT = qw(frobnicate); - sub frobnicate { my $n = shift; ... } + sub frobnicate { ... } 1; package MyScript; @@ -391,420 +391,32 @@ Its internal-facing interface is closer to Exporter.pm, with configuration done through the C<< @EXPORT >>, C<< @EXPORT_OK >> and C<< %EXPORT_TAGS >> package variables. -Exporter::Tiny performs most of its internal duties (including resolution -of tag names to sub names, resolution of sub names to coderefs, and -installation of coderefs into the target package) as method calls, which -means they can be overridden to provide interesting behaviour. - -=head2 Utility Functions - -These are really for internal use, but can be exported if you need them. - -=over - -=item C<< mkopt(\@array) >> - -Similar to C<mkopt> from L<Data::OptList>. It doesn't support all the -fancy options that Data::OptList does (C<moniker>, C<require_unique>, -C<must_be> and C<name_test>) but runs about 50% faster. - -=item C<< mkopt_hash(\@array) >> - -Similar to C<mkopt_hash> from L<Data::OptList>. See also C<mkopt>. - -=back - -=head1 TIPS AND TRICKS IMPORTING FROM EXPORTER::TINY - -For the purposes of this discussion we'll assume we have a module called -C<< MyUtils >> which exports one function, C<< frobnicate >>. C<< MyUtils >> -inherits from Exporter::Tiny. - -Many of these tricks may seem familiar from L<Sub::Exporter>. That is -intentional. Exporter::Tiny doesn't attempt to provide every feature of -Sub::Exporter, but where it does it usually uses a fairly similar API. - -=head2 Basic importing - - # import "frobnicate" function - use MyUtils "frobnicate"; - - # import all functions that MyUtils offers - use MyUtils -all; - -=head2 Renaming imported functions - - # call it "frob" - use MyUtils "frobnicate" => { -as => "frob" }; - - # call it "my_frobnicate" - use MyUtils "frobnicate" => { -prefix => "my_" }; - - # can set a prefix for *all* functions imported from MyUtils - # by placing the options hashref *first*. - use MyUtils { prefix => "my_" }, "frobnicate"; - # (note the lack of hyphen before `prefix`.) - - # call it "frobnicate_util" - use MyUtils "frobnicate" => { -suffix => "_util" }; - use MyUtils { suffix => "_util" }, "frobnicate"; - - # import it twice with two different names - use MyUtils - "frobnicate" => { -as => "frob" }, - "frobnicate" => { -as => "frbnct" }; - -=head2 Lexical subs - - { - use Sub::Exporter::Lexical lexical_installer => { -as => "lex" }; - use MyUtils { installer => lex }, "frobnicate"; - - frobnicate(...); # ok - } - - frobnicate(...); # not ok - -=head2 Import functions into another package - - use MyUtils { into => "OtherPkg" }, "frobnicate"; - - OtherPkg::frobincate(...); - -=head2 Import functions into a scalar - - my $func; - use MyUtils "frobnicate" => { -as => \$func }; - - $func->(...); - -=head2 Import functions into a hash - -OK, Sub::Exporter doesn't do this... - - my %funcs; - use MyUtils { into => \%funcs }, "frobnicate"; - - $funcs{frobnicate}->(...); - -=head2 DO NOT WANT! - -This imports everything except "frobnicate": - - use MyUtils qw( -all !frobnicate ); - -Negated imports always "win", so the following will not import -"frobnicate", no matter how many times you repeat it... - - use MyUtils qw( !frobnicate frobnicate frobnicate frobnicate ); - -=head2 Importing by regexp - -Here's how you could import all functions beginning with an "f": - - use MyUtils qw( /^F/i ); - -Or import everything except functions beginning with a "z": - - use MyUtils qw( -all !/^Z/i ); - -Note that regexps are always supplied as I<strings> starting with -C<< "/" >>, and not as quoted regexp references (C<< qr/.../ >>). - -=head2 Unimporting - -You can unimport the functions that MyUtils added to your namespace: - - no MyUtils; - -Or just specific ones: - - no MyUtils qw(frobnicate); - -If you renamed a function when you imported it, you should unimport by -the new name: - - use MyUtils frobnicate => { -as => "frob" }; - ...; - no MyUtils "frob"; - -Unimporting using tags and regexps should mostly do what you want. - -=head1 TIPS AND TRICKS EXPORTING USING EXPORTER::TINY - -Simple configuration works the same as L<Exporter>; inherit from this module, -and use the C<< @EXPORT >>, C<< @EXPORT_OK >> and C<< %EXPORT_TAGS >> -package variables to list subs to export. - -=head2 Generators - -Exporter::Tiny has always allowed exported subs to be generated (like -L<Sub::Exporter>), but until version 0.025 did not have an especially nice -API for it. - -Now, it's easy. If you want to generate a sub C<foo> to export, list it in -C<< @EXPORT >> or C<< @EXPORT_OK >> as usual, and then simply give your -exporter module a class method called C<< _generate_foo >>. - - push @EXPORT_OK, 'foo'; - - sub _generate_foo { - my $class = shift; - my ($name, $args, $globals) = @_; - - return sub { - ...; - } - } - -You can also generate tags: - - my %constants; - BEGIN { - %constants = (FOO => 1, BAR => 2); - } - use constant \%constants; - - $EXPORT_TAGS{constants} = sub { - my $class = shift; - my ($name, $args, $globals) = @_; - - return keys(%constants); - }; - -=head2 Overriding Internals - -An important difference between L<Exporter> and Exporter::Tiny is that -the latter calls all its internal functions as I<< class methods >>. This -means that your subclass can I<< override them >> to alter their behaviour. - -The following methods are available to be overridden. Despite being named -with a leading underscore, they are considered public methods. (The underscore -is there to avoid accidentally colliding with any of your own function names.) +If you are trying to B<write> a module that inherits from Exporter::Tiny, +then look at: =over -=item C<< _exporter_validate_opts($globals) >> - -This method is called once each time C<import> is called. It is passed a -reference to the global options hash. (That is, the optional leading hashref -in the C<use> statement, where the C<into> and C<installer> options can be -provided.) - -You may use this method to munge the global options, or validate them, -throwing an exception or printing a warning. - -The default implementation does nothing interesting. - -=item C<< _exporter_validate_unimport_opts($globals) >> - -Like C<_exporter_validate_opts>, but called for C<unimport>. - -=item C<< _exporter_merge_opts($tag_opts, $globals, @exports) >> - -Called to merge options which have been provided for a tag into the -options provided for the exports that the tag expanded to. - -=item C<< _exporter_expand_tag($name, $args, $globals) >> - -This method is called to expand an import tag (e.g. C<< ":constants" >>). -It is passed the tag name (minus the leading ":"), an optional hashref -of options (like C<< { -prefix => "foo_" } >>), and the global options -hashref. - -It is expected to return a list of ($name, $args) arrayref pairs. These -names can be sub names to export, or further tag names (which must have -their ":"). If returning tag names, be careful to avoid creating a tag -expansion loop! - -The default implementation uses C<< %EXPORT_TAGS >> to expand tags, and -provides fallbacks for the C<< :default >> and C<< :all >> tags. - -=item C<< _exporter_expand_regexp($regexp, $args, $globals) >> - -Like C<_exporter_expand_regexp>, but given a regexp-like string instead -of a tag name. +=item * -The default implementation greps through C<< @EXPORT_OK >> for imports, -and the list of already-imported functions for exports. +L<Exporter::Tiny::Manual::QuickStart> -=item C<< _exporter_expand_sub($name, $args, $globals) >> +=item * -This method is called to translate a sub name to a hash of name => coderef -pairs for exporting to the caller. In general, this would just be a hash with -one key and one value, but, for example, L<Type::Library> overrides this -method so that C<< "+Foo" >> gets expanded to: - - ( - Foo => sub { $type }, - is_Foo => sub { $type->check(@_) }, - to_Foo => sub { $type->assert_coerce(@_) }, - assert_Foo => sub { $type->assert_return(@_) }, - ) - -The default implementation checks that the name is allowed to be exported -(using the C<_exporter_permitted_regexp> method), gets the coderef using -the generator if there is one (or by calling C<< can >> on your exporter -otherwise) and calls C<_exporter_fail> if it's unable to generate or -retrieve a coderef. - -=item C<< _exporter_permitted_regexp($globals) >> - -This method is called to retrieve a regexp for validating the names of -exportable subs. If a sub doesn't match the regexp, then the default -implementation of C<_exporter_expand_sub> will refuse to export it. (Of -course, you may override the default C<_exporter_expand_sub>.) - -The default implementation of this method assembles the regexp from -C<< @EXPORT >> and C<< @EXPORT_OK >>. - -=item C<< _exporter_fail($name, $args, $globals) >> - -Called by C<_exporter_expand_sub> if it can't find a coderef to export. - -The default implementation just throws an exception. But you could emit -a warning instead, or just ignore the failed export. - -If you don't throw an exception then you should be aware that this -method is called in list context, and any list it returns will be treated -as an C<_exporter_expand_sub>-style hash of names and coderefs for -export. - -=item C<< _exporter_install_sub($name, $args, $globals, $coderef) >> - -This method actually installs the exported sub into its new destination. -Its return value is ignored. - -The default implementation handles sub renaming (i.e. the C<< -as >>, -C<< -prefix >> and C<< -suffix >> functions. This method does a lot of -stuff; if you need to override it, it's probably a good idea to just -pre-process the arguments and then call the super method rather than -trying to handle all of it yourself. - -=item C<< _exporter_uninstall_sub($name, $args, $globals) >> - -The opposite of C<_exporter_install_sub>. +L<Exporter::Tiny::Manual::Exporting> =back -=head1 DIAGNOSTICS +If you are trying to B<use> a module that inherits from Exporter::Tiny, +then look at: =over -=item B<< Overwriting existing sub '%s::%s' with sub '%s' exported by %s >> - -A warning issued if Exporter::Tiny is asked to export a symbol which -will result in an existing sub being overwritten. This warning can be -suppressed using either of the following: +=item * - use MyUtils { replace => 1 }, "frobnicate"; - use MyUtils "frobnicate" => { -replace => 1 }; - -Or can be upgraded to a fatal error: - - use MyUtils { replace => "die" }, "frobnicate"; - use MyUtils "frobnicate" => { -replace => "die" }; - -=item B<< Refusing to overwrite existing sub '%s::%s' with sub '%s' exported by %s >> - -The fatal version of the above warning. - -=item B<< Could not find sub '%s' exported by %s >> - -You requested to import a sub which the package does not provide. - -=item B<< Cannot provide an -as option for tags >> - -Because a tag may provide more than one function, it does not make sense -to request a single name for it. Instead use C<< -prefix >> or C<< -suffix >>. - -=item B<< Passing options to unimport '%s' makes no sense >> - -When you import a sub, it occasionally makes sense to pass some options -for it. However, when unimporting, options do nothing, so this warning -is issued. +L<Exporter::Tiny::Manual::Importing> =back -=head1 HISTORY - -L<Type::Library> had a bunch of custom exporting code which poked coderefs -into its caller's stash. It needed this to be something more powerful than -most exporters so that it could switch between exporting Moose, Mouse and -Moo-compatible objects on request. L<Sub::Exporter> would have been capable, -but had too many dependencies for the Type::Tiny project. - -Meanwhile L<Type::Utils>, L<Types::TypeTiny> and L<Test::TypeTiny> each -used the venerable L<Exporter.pm|Exporter>. However, this meant they were -unable to use the features like L<Sub::Exporter>-style function renaming -which I'd built into Type::Library: - - ## import "Str" but rename it to "String". - use Types::Standard "Str" => { -as => "String" }; - -And so I decided to factor out code that could be shared by all Type-Tiny's -exporters into a single place: Exporter::TypeTiny. - -As of version 0.026, Exporter::TypeTiny was also made available as -L<Exporter::Tiny>, distributed independently on CPAN. CHOCOLATEBOY had -convinced me that it was mature enough to live a life of its own. - -As of version 0.030, Type-Tiny depends on Exporter::Tiny and -Exporter::TypeTiny is being phased out. - -=head1 OBLIGATORY EXPORTER COMPARISON - -Exporting is unlikely to be your application's performance bottleneck, but -nonetheless here are some comparisons. - -B<< Comparative sizes according to L<Devel::SizeMe>: >> - - Exporter 217.1Kb - Sub::Exporter::Progressive 263.2Kb - Exporter::Tiny 267.7Kb - Exporter + Exporter::Heavy 281.5Kb - Exporter::Renaming 406.2Kb - Sub::Exporter 701.0Kb - -B<< Performance exporting a single sub: >> - - Rate SubExp ExpTiny SubExpProg ExpPM -SubExp 2489/s -- -56% -85% -88% -ExpTiny 5635/s 126% -- -67% -72% -SubExpProg 16905/s 579% 200% -- -16% -ExpPM 20097/s 707% 257% 19% -- - -(Exporter::Renaming globally changes the behaviour of Exporter.pm, so could -not be included in the same benchmarks.) - -B<< (Non-Core) Dependencies: >> - - Exporter -1 - Exporter::Renaming 0 - Exporter::Tiny 0 - Sub::Exporter::Progressive 0 - Sub::Exporter 3 - -B<< Features: >> - - ExpPM ExpTiny SubExp SubExpProg - Can export code symbols............. Yes Yes Yes Yes - Can export non-code symbols......... Yes - Groups/tags......................... Yes Yes Yes Yes - Export by regexp.................... Yes Yes - Bang prefix......................... Yes Yes - Allows renaming of subs............. Yes Yes Maybe - Install code into scalar refs....... Yes Yes Maybe - Can be passed an "into" parameter... Yes Yes Maybe - Can be passed an "installer" sub.... Yes Yes Maybe - Config avoids package variables..... Yes - Supports generators................. Yes Yes - Sane API for generators............. Yes Yes - Unimport............................ Yes - -(Certain Sub::Exporter::Progressive features are only available if -Sub::Exporter is installed.) - =head1 BUGS Please report any bugs to @@ -817,9 +429,9 @@ on L<irc.perl.org|http://www.irc.perl.org/channels.html>. =head1 SEE ALSO -L<Exporter::Shiny>, -L<Sub::Exporter>, -L<Exporter>. +Simplified interface to this module: L<Exporter::Shiny>. + +Other interesting exporters: L<Sub::Exporter>, L<Exporter>. =head1 AUTHOR diff --git a/lib/Exporter/Tiny/Manual/Etc.pm b/lib/Exporter/Tiny/Manual/Etc.pm new file mode 100644 index 0000000..3f5a8d2 --- /dev/null +++ b/lib/Exporter/Tiny/Manual/Etc.pm @@ -0,0 +1,134 @@ +=pod + +=encoding utf-8 + +=for stopwords frobnicate greps regexps + +=head1 NAME + +Exporter::Tiny::Manual::Etc - odds and ends + +=head1 DESCRIPTION + +=head2 Utility Functions + +Exporter::Tiny is itself an exporter! + +These functions are really for internal use, but can be exported if you +need them: + +=over + +=item C<< mkopt(\@array) >> + +Similar to C<mkopt> from L<Data::OptList>. It doesn't support all the +fancy options that Data::OptList does (C<moniker>, C<require_unique>, +C<must_be> and C<name_test>) but runs about 50% faster. + +=item C<< mkopt_hash(\@array) >> + +Similar to C<mkopt_hash> from L<Data::OptList>. See also C<mkopt>. + +=back + +=head2 History + +L<Type::Library> had a bunch of custom exporting code which poked coderefs +into its caller's stash. It needed this to be something more powerful than +most exporters so that it could switch between exporting Moose, Mouse and +Moo-compatible objects on request. L<Sub::Exporter> would have been capable, +but had too many dependencies for the Type::Tiny project. + +Meanwhile L<Type::Utils>, L<Types::TypeTiny> and L<Test::TypeTiny> each +used the venerable L<Exporter.pm|Exporter>. However, this meant they were +unable to use the features like L<Sub::Exporter>-style function renaming +which I'd built into Type::Library: + + ## import "Str" but rename it to "String". + use Types::Standard "Str" => { -as => "String" }; + +And so I decided to factor out code that could be shared by all Type-Tiny's +exporters into a single place: Exporter::TypeTiny. + +As of version 0.026, Exporter::TypeTiny was also made available as +L<Exporter::Tiny>, distributed independently on CPAN. CHOCOLATEBOY had +convinced me that it was mature enough to live a life of its own. + +As of version 0.030, Type-Tiny depends on Exporter::Tiny and +Exporter::TypeTiny is being phased out. + +=head2 Obligatory Exporter Comparison + +Exporting is unlikely to be your application's performance bottleneck, but +nonetheless here are some comparisons. + +B<< Comparative sizes according to L<Devel::SizeMe>: >> + + Exporter 217.1Kb + Sub::Exporter::Progressive 263.2Kb + Exporter::Tiny 267.7Kb + Exporter + Exporter::Heavy 281.5Kb + Exporter::Renaming 406.2Kb + Sub::Exporter 701.0Kb + +B<< Performance exporting a single sub: >> + + Rate SubExp ExpTiny SubExpProg ExpPM +SubExp 2489/s -- -56% -85% -88% +ExpTiny 5635/s 126% -- -67% -72% +SubExpProg 16905/s 579% 200% -- -16% +ExpPM 20097/s 707% 257% 19% -- + +(Exporter::Renaming globally changes the behaviour of Exporter.pm, so could +not be included in the same benchmarks.) + +B<< (Non-Core) Dependencies: >> + + Exporter -1 + Exporter::Renaming 0 + Exporter::Tiny 0 + Sub::Exporter::Progressive 0 + Sub::Exporter 3 + +B<< Features: >> + + ExpPM ExpTiny SubExp SubExpProg + Can export code symbols............. Yes Yes Yes Yes + Can export non-code symbols......... Yes + Groups/tags......................... Yes Yes Yes Yes + Export by regexp.................... Yes Yes + Bang prefix......................... Yes Yes + Allows renaming of subs............. Yes Yes Maybe + Install code into scalar refs....... Yes Yes Maybe + Can be passed an "into" parameter... Yes Yes Maybe + Can be passed an "installer" sub.... Yes Yes Maybe + Config avoids package variables..... Yes + Supports generators................. Yes Yes + Sane API for generators............. Yes Yes + Unimport............................ Yes + +(Certain Sub::Exporter::Progressive features are only available if +Sub::Exporter is installed.) + +=head1 SEE ALSO + +L<Exporter::Shiny>, +L<Exporter::Tiny>. + +=head1 AUTHOR + +Toby Inkster E<lt>toby...@cpan.orge<gt>. + +=head1 COPYRIGHT AND LICENCE + +This software is copyright (c) 2013-2014 by Toby Inkster. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=head1 DISCLAIMER OF WARRANTIES + +THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + diff --git a/lib/Exporter/Tiny/Manual/Exporting.pm b/lib/Exporter/Tiny/Manual/Exporting.pm new file mode 100644 index 0000000..49ef71f --- /dev/null +++ b/lib/Exporter/Tiny/Manual/Exporting.pm @@ -0,0 +1,256 @@ +=pod + +=encoding utf-8 + +=for stopwords frobnicate greps regexps + +=head1 NAME + +Exporter::Tiny::Manual::Exporting - creating an exporter using Exporter::Tiny + +=head1 SYNOPSIS + +B<< Read L<Exporter::Tiny::Manual::QuickStart> first! >> + +=head1 DESCRIPTION + +Simple configuration works the same as L<Exporter>; inherit from +L<Exporter::Tiny>, and use the C<< @EXPORT >>, C<< @EXPORT_OK >>, +and C<< %EXPORT_TAGS >> package variables to list subs to export. + +Unlike Exporter, Exporter::Tiny performs most of its internal duties +(including resolution of tag names to sub names, resolution of sub +names to coderefs, and installation of coderefs into the target +package) as B<method calls>, which means that your module (which is a +subclass of Exporter::Tiny) can override them to provide interesting +behaviour. + +=head2 Advanced Tag Stuff + +You can define tags using other tags: + + use Exporter::Shiny qw( + black white red green blue cyan magenta yellow + ); + + our %EXPORT_TAGS = ( + rgb => [qw( red green blue )], + cym => [qw( cyan magenta yellow )], + cymk => [qw( black :cym )], + monochrome => [qw( black white )], + all => [qw( :rgb :cymk :monochrome )], + ); + +B<< CAVEAT: >> If you create a cycle in the tags, this could put +Exporter::Tiny into an infinite loop expanding the tags. Don't do that. + +=head2 More on Generators + +Exporter::Tiny has always allowed exported subs to be generated (like +L<Sub::Exporter>), but until version 0.025 did not have an especially nice +API for it. + +Now, it's easy. If you want to generate a sub C<foo> to export, list it in +C<< @EXPORT >> or C<< @EXPORT_OK >> as usual, and then simply give your +exporter module a class method called C<< _generate_foo >>. + + push @EXPORT_OK, 'foo'; + + sub _generate_foo { + my $class = shift; + my ($name, $args, $globals) = @_; + + return sub { + ...; + } + } + +We showed how to do that in L<Exporter::Tiny::Manual::QuickStart>, but +one thing we didn't show was that C<< $globals >> gets passed in there. +This is the global options hash, as described in +L<Exporter::Tiny::Manual::Importing>. It can often be useful. In +particular it will tell you what package the generated sub is destined +to be installed into. + +You can also generate tags: + + my %constants; + BEGIN { + %constants = (FOO => 1, BAR => 2); + } + use constant \%constants; + + $EXPORT_TAGS{constants} = sub { + my $class = shift; + my ($name, $args, $globals) = @_; + + return keys(%constants); + }; + +=head2 Hooks + +Sometimes as well as exporting stuff, you want to do some setup or +something. + +You can define a couple of class methods in your package, and they'll +get called at the appropriate time: + + package MyUtils; + + ...; + + sub _exporter_validate_opts { + my $class = shift; + my ($globals) = @_; + + ...; # do stuff here + + $class->SUPER::_exporter_validate_opts(@_); + } + + sub _exporter_validate_unimport_opts { + my $class = shift; + my ($globals) = @_; + + ...; # do stuff here + + $class->SUPER::_exporter_validate_unimport_opts(@_); + } + +The C<< $globals >> variable is that famous global options hash. In +particular, C<< $globals->{into} >> is useful because it tells you what +package has imported you. + +As you might have guessed, these methods were originally intended to +validate the global options hash, but can be used to perform any +general duties before the real exporting work is done. + +=head2 Overriding Internals + +An important difference between L<Exporter> and Exporter::Tiny is that +the latter calls all its internal functions as I<< class methods >>. This +means that your subclass can I<< override them >> to alter their behaviour. + +The following methods are available to be overridden. Despite being named +with a leading underscore, they are considered public methods. (The underscore +is there to avoid accidentally colliding with any of your own function names.) + +=over + +=item C<< _exporter_validate_opts($globals) >> + +Documented above. + +=item C<< _exporter_validate_unimport_opts($globals) >> + +Documented above. + +=item C<< _exporter_merge_opts($tag_opts, $globals, @exports) >> + +Called to merge options which have been provided for a tag into the +options provided for the exports that the tag expanded to. + +=item C<< _exporter_expand_tag($name, $args, $globals) >> + +This method is called to expand an import tag (e.g. C<< ":constants" >>). +It is passed the tag name (minus the leading ":"), an optional hashref +of options (like C<< { -prefix => "foo_" } >>), and the global options +hashref. + +It is expected to return a list of ($name, $args) arrayref pairs. These +names can be sub names to export, or further tag names (which must have +their ":"). If returning tag names, be careful to avoid creating a tag +expansion loop! + +The default implementation uses C<< %EXPORT_TAGS >> to expand tags, and +provides fallbacks for the C<< :default >> and C<< :all >> tags. + +=item C<< _exporter_expand_regexp($regexp, $args, $globals) >> + +Like C<_exporter_expand_regexp>, but given a regexp-like string instead +of a tag name. + +The default implementation greps through C<< @EXPORT_OK >> for imports, +and the list of already-imported functions for exports. + +=item C<< _exporter_expand_sub($name, $args, $globals) >> + +This method is called to translate a sub name to a hash of name => coderef +pairs for exporting to the caller. In general, this would just be a hash with +one key and one value, but, for example, L<Type::Library> overrides this +method so that C<< "+Foo" >> gets expanded to: + + ( + Foo => sub { $type }, + is_Foo => sub { $type->check(@_) }, + to_Foo => sub { $type->assert_coerce(@_) }, + assert_Foo => sub { $type->assert_return(@_) }, + ) + +The default implementation checks that the name is allowed to be exported +(using the C<_exporter_permitted_regexp> method), gets the coderef using +the generator if there is one (or by calling C<< can >> on your exporter +otherwise) and calls C<_exporter_fail> if it's unable to generate or +retrieve a coderef. + +=item C<< _exporter_permitted_regexp($globals) >> + +This method is called to retrieve a regexp for validating the names of +exportable subs. If a sub doesn't match the regexp, then the default +implementation of C<_exporter_expand_sub> will refuse to export it. (Of +course, you may override the default C<_exporter_expand_sub>.) + +The default implementation of this method assembles the regexp from +C<< @EXPORT >> and C<< @EXPORT_OK >>. + +=item C<< _exporter_fail($name, $args, $globals) >> + +Called by C<_exporter_expand_sub> if it can't find a coderef to export. + +The default implementation just throws an exception. But you could emit +a warning instead, or just ignore the failed export. + +If you don't throw an exception then you should be aware that this +method is called in list context, and any list it returns will be treated +as an C<_exporter_expand_sub>-style hash of names and coderefs for +export. + +=item C<< _exporter_install_sub($name, $args, $globals, $coderef) >> + +This method actually installs the exported sub into its new destination. +Its return value is ignored. + +The default implementation handles sub renaming (i.e. the C<< -as >>, +C<< -prefix >> and C<< -suffix >> functions. This method does a lot of +stuff; if you need to override it, it's probably a good idea to just +pre-process the arguments and then call the super method rather than +trying to handle all of it yourself. + +=item C<< _exporter_uninstall_sub($name, $args, $globals) >> + +The opposite of C<_exporter_install_sub>. + +=back + +=head1 SEE ALSO + +L<Exporter::Shiny>, +L<Exporter::Tiny>. + +=head1 AUTHOR + +Toby Inkster E<lt>toby...@cpan.orge<gt>. + +=head1 COPYRIGHT AND LICENCE + +This software is copyright (c) 2013-2014 by Toby Inkster. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=head1 DISCLAIMER OF WARRANTIES + +THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + diff --git a/lib/Exporter/Tiny/Manual/Importing.pm b/lib/Exporter/Tiny/Manual/Importing.pm new file mode 100644 index 0000000..362a696 --- /dev/null +++ b/lib/Exporter/Tiny/Manual/Importing.pm @@ -0,0 +1,253 @@ +=pod + +=encoding utf-8 + +=for stopwords frobnicate greps regexps + +=head1 NAME + +Exporter::Tiny::Manual::Importing - importing from Exporter::Tiny-based modules + +=head1 DESCRIPTION + +For the purposes of this discussion we'll assume we have a module called +C<< MyUtils >> which exports functions called C<frobnicate>, C<red>, +C<blue>, and C<green>. It has a tag set up called C<:colours> which +corresponds to C<red>, C<blue>, and C<green>. + +Many of these tricks may seem familiar from L<Sub::Exporter>. That is +intentional. Exporter::Tiny doesn't attempt to provide every feature of +Sub::Exporter, but where it does it usually uses a fairly similar API. + +=head2 Basic importing + +It's easy to import a single function from a module: + + use MyUtils "frobnicate"; + +Or a list of functions: + + use MyUtils "red", "green"; + +Perl's C<< qw() >> shorthand for a list of words is pretty useful: + + use MyUtils qw( red green ); + +If the module defines tags, you can import them like this: + + use MyUtils qw( :colours ); + +Or with a hyphen instead of a colon: + + use MyUtils qw( -colours ); + +Hyphens are good because Perl will autoquote a bareword that follows +them: + + use MyUtils -colours; + +And it's possible to mix function names and tags in the same list: + + use MyUtils qw( frobnicate :colours ); + +=head2 Renaming imported functions + +It's possible to rename a function you're importing: + + use MyUtils "frobnicate" => { -as => "frob" }; + +Or you can apply a prefix and/or suffix. The following imports the +function and calls it C<my_frobinate_thing>. + + use MyUtils "frobnicate" => { -prefix => "my_", -suffix => "_thing" }; + +You can apply a prefix/suffix to B<all> functions you import by +placing the hashref B<first> in the import list. (This first hashref +is referred to as the global options hash, and can do some special +things.) + + use MyUtils { prefix => "my_" }, "frobnicate"; + +Did you notice that we used C<< -prefix >> and C<< -suffix >> in the +normal options hash, but C<< prefix >> and C<< suffix >> (no hyphen) +in the global options hash? That's a common pattern with this module. + +You can import the same function multiple times with different names: + + use MyUtils + "frobnicate" => { -as => "frob" }, + "frobnicate" => { -as => "frbnct" }; + +Tags can take the C<< -prefix >> and C<< -suffix >> options too. The +following imports C<colour_red>, C<colour_green>, and C<colour_blue>: + + use MyUtils -colours => { -prefix => "colour_" }; + +You can also set C<< -as >> to be a coderef to generate a function +name. This imports functions called C<RED>, C<GREEN>, and C<BLUE>: + + use MyUtils -colours => { -as => sub { uc($_[0]) } }; + +Note that it doesn't make sense to use C<< -as >> with a tag unless +you're doing this coderef thing. Coderef C<< as >> also works in the +global options hash. + +=head2 DO NOT WANT! + +Sometimes you want to supply a list of functions you B<< don't >> want +to import. To do that, prefix the function with a bang. This imports +everything except "frobnicate": + + use MyUtils qw( -all !frobnicate ); + +You can add the bang prefix to tags too. This will import everything +except the colours. + + use MyUtils qw( -all !:colours ); + +Negated imports always "win", so the following will not import +"frobnicate", no matter how many times you repeat it... + + use MyUtils qw( !frobnicate frobnicate frobnicate frobnicate ); + +=head2 Importing by regexp + +Here's how you could import all functions beginning with an "f": + + use MyUtils qw( /^F/i ); + +Or import everything except functions beginning with a "z": + + use MyUtils qw( -all !/^Z/i ); + +Note that regexps are always supplied as I<strings> starting with +C<< "/" >>, and not as quoted regexp references (C<< qr/.../ >>). + +=head2 Import functions into another package + +Occasionally you need to import functions not into your own package, +but into a different package. You can do that like this: + + use MyUtils { into => "OtherPkg" }, "frobnicate"; + + OtherPkg::frobincate(...); + +However, L<Import::Into> will probably provide you with a better +approach which doesn't just work with Exporter::Tiny, but B<all> +exporters. + +=head2 Lexical subs + +Often you want to make use of an exported function, but don't want +it to "pollute" your namespace. + +There is this L<Sub::Exporter::Lexical> thing that was designed as a +plugin for L<Sub::Exporter>, but Exporter::Tiny's API is close enough +that it will work. Do you remember that global options hash? Just +use that to tell Exporter::Tiny to use an alternative sub installer. + + { + use Sub::Exporter::Lexical lexical_installer => { -as => "lex" }; + use MyUtils { installer => lex }, "frobnicate"; + + frobnicate(...); # ok + } + + frobnicate(...); # not ok + +Another way to do lexical functions is to import a function into a +scalar variable: + + my $func; + use MyUtils "frobnicate" => { -as => \$func }; + + $func->(...); + +You can even provide a hashref to put all imported functions into as +part of that global options hash I mentioned earlier. + + my %funcs; + use MyUtils { into => \%funcs }, "frobnicate"; + + $funcs{frobnicate}->(...); + +=head2 Unimporting + +You can unimport the functions that MyUtils added to your namespace: + + no MyUtils; + +Or just specific ones: + + no MyUtils qw(frobnicate); + +If you renamed a function when you imported it, you should unimport by +the new name: + + use MyUtils frobnicate => { -as => "frob" }; + ...; + no MyUtils "frob"; + +Unimporting using tags and regexps should mostly do what you want. + +=head1 DIAGNOSTICS + +=over + +=item B<< Overwriting existing sub '%s::%s' with sub '%s' exported by %s >> + +A warning issued if Exporter::Tiny is asked to export a symbol which +will result in an existing sub being overwritten. This warning can be +suppressed using either of the following: + + use MyUtils { replace => 1 }, "frobnicate"; + use MyUtils "frobnicate" => { -replace => 1 }; + +Or can be upgraded to a fatal error: + + use MyUtils { replace => "die" }, "frobnicate"; + use MyUtils "frobnicate" => { -replace => "die" }; + +=item B<< Refusing to overwrite existing sub '%s::%s' with sub '%s' exported by %s >> + +The fatal version of the above warning. + +=item B<< Could not find sub '%s' exported by %s >> + +You requested to import a sub which the package does not provide. + +=item B<< Cannot provide an -as option for tags >> + +Because a tag may provide more than one function, it does not make sense +to request a single name for it. Instead use C<< -prefix >> or C<< -suffix >>. + +=item B<< Passing options to unimport '%s' makes no sense >> + +When you import a sub, it occasionally makes sense to pass some options +for it. However, when unimporting, options do nothing, so this warning +is issued. + +=back + +=head1 SEE ALSO + +L<Exporter::Shiny>, +L<Exporter::Tiny>. + +=head1 AUTHOR + +Toby Inkster E<lt>toby...@cpan.orge<gt>. + +=head1 COPYRIGHT AND LICENCE + +This software is copyright (c) 2013-2014 by Toby Inkster. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=head1 DISCLAIMER OF WARRANTIES + +THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + diff --git a/lib/Exporter/Tiny/Manual/QuickStart.pm b/lib/Exporter/Tiny/Manual/QuickStart.pm new file mode 100644 index 0000000..def8701 --- /dev/null +++ b/lib/Exporter/Tiny/Manual/QuickStart.pm @@ -0,0 +1,195 @@ +=pod + +=encoding utf-8 + +=for stopwords frobnicate greps regexps + +=head1 NAME + +Exporter::Tiny::Manual::QuickStart - the quickest way to get up and running with Exporter::Tiny + +=head1 SYNOPSIS + + package MyUtils; + + use Exporter::Shiny qw( frobnicate ); + + sub frobnicate { + ...; # your code here + } + + 1; + +Now people can use your module like this: + + use MyUtils "frobnicate"; + + frobnicate(42); + +Or like this: + + use MyUtils "frobnicate" => { -as => "frob" }; + + frob(42); + +=head1 DESCRIPTION + +See the synopsis. Yes, it's that simple. + +=head2 Next steps + +=head3 Default exports + +Note that the module in the synopsis doesn't export anything by default. +If people load C<MyUtils> like this: + + use MyUtils; + +Then they haven't imported any functions. You can specify a default set +of functions to be exported like this: + + package MyUtils; + + use Exporter::Shiny qw( frobnicate ); + + our @EXPORT = qw( frobnicate ); + + sub frobnicate { ... } + + 1; + +Or, if you want to be a superstar rock god: + + package MyUtils; + + use Exporter::Shiny our @EXPORT = qw( frobnicate ); + + sub frobnicate { ... } + + 1; + +=head3 Tags + +You can provide tags for people to use: + + package MyUtils; + + use Exporter::Shiny qw( frobnicate red green blue ); + + our %EXPORT_TAGS = ( + utils => [qw/ frobnicate /], + colours => [qw/ red green blue /], + ); + + sub frobnicate { ... } + sub red { ... } + sub green { ... } + sub blue { ... } + + 1; + +And people can now import your functions like this: + + use MyUtils ":colours"; + +Or this: + + use MyUtils "-colours"; + +Or take advantage of the fact that Perl magically quotes barewords +preceded by a hyphen: + + use MyUtils -colours; + +Two tags are automatically defined for you: C<< -default >> (which is +just the same as C<< @EXPORT >>) and C<< -all >> (which is the union of +C<< @EXPORT >> and C<< @EXPORT_OK >>). If you don't like them, then you +can override them: + + our %EXPORT_TAGS = ( + default => \@some_other_stuff, + all => \@more_stuff, + ); + +=head3 Generators + +Exporting normally just works by copying a sub from your package into +your caller's package. But sometimes it's useful instead to generate +a I<custom> sub to insert into your caller's package. This is pretty +easy to do. + + package MyUtils; + + use Exporter::Shiny qw( frobnicate ); + + sub _generate_frobnicate { + my $me = shift; + my $caller = caller; + my ($name, $args) = @_; + + return sub { + ...; # your code here + }; + } + + 1; + +The parameter C<< $me >> here is a string containing the package name +which is being imported from; C<< $caller >> is the destination package; +C<< $name >> is the name of the sub (in this case "frobnicate"); and +C<< $args >> is a hashref of custom arguments for this function. + + # The hashref { foo => 42 } is $args above. + # + use MyUtils "frobnicate" => { foo => 42 }; + +=head2 Avoiding Exporter::Shiny + +Exporter::Shiny is a tiny shim around Exporter::Tiny. It should mostly +do what you want, but you may sometimes prefer to use Exporter::Tiny +directly. + +The example in the synopsis could have been written as: + + package MyUtils; + + use parent "Exporter::Tiny"; + our @EXPORT_OK = qw( frobnicate ); + + sub frobnicate { + ...; # your code here + } + + 1; + +What Exporter::Shiny does is mostly just to set C<< @EXPORT_OK >> for +you and set up inheritance from the base class (Exporter::Tiny). + +Exporter::Shiny also sets C<< $INC{'MyUtils.pm} >> for you, which in +usually makes little difference, but is useful in some edge cases. + +=head1 SEE ALSO + +L<Exporter::Shiny>, +L<Exporter::Tiny>. + +For more advanced information, see +L<Exporter::Tiny::Manual::Exporting>. + +=head1 AUTHOR + +Toby Inkster E<lt>toby...@cpan.orge<gt>. + +=head1 COPYRIGHT AND LICENCE + +This software is copyright (c) 2013-2014 by Toby Inkster. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=head1 DISCLAIMER OF WARRANTIES + +THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libexporter-tiny-perl.git _______________________________________________ Pkg-perl-cvs-commits mailing list Pkg-perl-cvs-commits@lists.alioth.debian.org http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-perl-cvs-commits