diff options
Diffstat (limited to 'lib/Sub/Exporter/Tutorial.pod')
-rw-r--r-- | lib/Sub/Exporter/Tutorial.pod | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/lib/Sub/Exporter/Tutorial.pod b/lib/Sub/Exporter/Tutorial.pod new file mode 100644 index 0000000..6674b2c --- /dev/null +++ b/lib/Sub/Exporter/Tutorial.pod @@ -0,0 +1,280 @@ + +# PODNAME: Sub::Exporter::Tutorial +# ABSTRACT: a friendly guide to exporting with Sub::Exporter + +__END__ + +=pod + +=head1 NAME + +Sub::Exporter::Tutorial - a friendly guide to exporting with Sub::Exporter + +=head1 VERSION + +version 0.987 + +=head1 DESCRIPTION + +=head2 What's an Exporter? + +When you C<use> a module, first it is required, then its C<import> method is +called. The Perl documentation tells us that the following two lines are +equivalent: + + use Module LIST; + + BEGIN { require Module; Module->import(LIST); } + +The method named C<import> is the module's I<exporter>, it exports +functions and variables into its caller's namespace. + +=head2 The Basics of Sub::Exporter + +Sub::Exporter builds a custom exporter which can then be installed into your +module. It builds this method based on configuration passed to its +C<setup_exporter> method. + +A very basic use case might look like this: + + package Addition; + use Sub::Exporter; + Sub::Exporter::setup_exporter({ exports => [ qw(plus) ]}); + + sub plus { my ($x, $y) = @_; return $x + $y; } + +This would mean that when someone used your Addition module, they could have +its C<plus> routine imported into their package: + + use Addition qw(plus); + + my $z = plus(2, 2); # this works, because now plus is in the main package + +That syntax to set up the exporter, above, is a little verbose, so for the +simple case of just naming some exports, you can write this: + + use Sub::Exporter -setup => { exports => [ qw(plus) ] }; + +...which is the same as the original example -- except that now the exporter is +built and installed at compile time. Well, that and you typed less. + +=head2 Using Export Groups + +You can specify whole groups of things that should be exportable together. +These are called groups. L<Exporter> calls these tags. To specify groups, you +just pass a C<groups> key in your exporter configuration: + + package Food; + use Sub::Exporter -setup => { + exports => [ qw(apple banana beef fluff lox rabbit) ], + groups => { + fauna => [ qw(beef lox rabbit) ], + flora => [ qw(apple banana) ], + } + }; + +Now, to import all that delicious foreign meat, your consumer needs only to +write: + + use Food qw(:fauna); + use Food qw(-fauna); + +Either one of the above is acceptable. A colon is more traditional, but +barewords with a leading colon can't be enquoted by a fat arrow. We'll see why +that matters later on. + +Groups can contain other groups. If you include a group name (with the leading +dash or colon) in a group definition, it will be expanded recursively when the +exporter is called. The exporter will B<not> recurse into the same group twice +while expanding groups. + +There are two special groups: C<all> and C<default>. The C<all> group is +defined for you and contains all exportable subs. You can redefine it, +if you want to export only a subset when all exports are requested. The +C<default> group is the set of routines to export when nothing specific is +requested. By default, there is no C<default> group. + +=head2 Renaming Your Imports + +Sometimes you want to import something, but you don't like the name as which +it's imported. Sub::Exporter can rename your imports for you. If you wanted +to import C<lox> from the Food package, but you don't like the name, you could +write this: + + use Food lox => { -as => 'salmon' }; + +Now you'd get the C<lox> routine, but it would be called salmon in your +package. You can also rename entire groups by using the C<prefix> option: + + use Food -fauna => { -prefix => 'cute_little_' }; + +Now you can call your C<cute_little_rabbit> routine. (You can also call +C<cute_little_beef>, but that hardly seems as enticing.) + +When you define groups, you can include renaming. + + use Sub::Exporter -setup => { + exports => [ qw(apple banana beef fluff lox rabbit) ], + groups => { + fauna => [ qw(beef lox), rabbit => { -as => 'coney' } ], + } + }; + +A prefix on a group like that does the right thing. This is when it's useful +to use a dash instead of a colon to indicate a group: you can put a fat arrow +between the group and its arguments, then. + + use Food -fauna => { -prefix => 'lovely_' }; + + eat( lovely_coney ); # this works + +Prefixes also apply recursively. That means that this code works: + + use Sub::Exporter -setup => { + exports => [ qw(apple banana beef fluff lox rabbit) ], + groups => { + fauna => [ qw(beef lox), rabbit => { -as => 'coney' } ], + allowed => [ -fauna => { -prefix => 'willing_' }, 'banana' ], + } + }; + + ... + + use Food -allowed => { -prefix => 'any_' }; + + $dinner = any_willing_coney; # yum! + +Groups can also be passed a C<-suffix> argument. + +Finally, if the C<-as> argument to an exported routine is a reference to a +scalar, a reference to the routine will be placed in that scalar. + +=head2 Building Subroutines to Order + +Sometimes, you want to export things that you don't have on hand. You might +want to offer customized routines built to the specification of your consumer; +that's just good business! With Sub::Exporter, this is easy. + +To offer subroutines to order, you need to provide a generator when you set up +your exporter. A generator is just a routine that returns a new routine. +L<perlref> is talking about these when it discusses closures and function +templates. The canonical example of a generator builds a unique incrementor; +here's how you'd do that with Sub::Exporter; + + package Package::Counter; + use Sub::Exporter -setup => { + exports => [ counter => sub { my $i = 0; sub { $i++ } } ], + groups => { default => [ qw(counter) ] }, + }; + +Now anyone can use your Package::Counter module and he'll receive a C<counter> +in his package. It will count up by one, and will never interfere with anyone +else's counter. + +This isn't very useful, though, unless the consumer can explain what he wants. +This is done, in part, by supplying arguments when importing. The following +example shows how a generator can take and use arguments: + + package Package::Counter; + + sub _build_counter { + my ($class, $name, $arg) = @_; + $arg ||= {}; + my $i = $arg->{start} || 0; + return sub { $i++ }; + } + + use Sub::Exporter -setup => { + exports => [ counter => \'_build_counter' ], + groups => { default => [ qw(counter) ] }, + }; + +Now, the consumer can (if he wants) specify a starting value for his counter: + + use Package::Counter counter => { start => 10 }; + +Arguments to a group are passed along to the generators of routines in that +group, but Sub::Exporter arguments -- anything beginning with a dash -- are +never passed in. When groups are nested, the arguments are merged as the +groups are expanded. + +Notice, too, that in the example above, we gave a reference to a method I<name> +rather than a method I<implementation>. By giving the name rather than the +subroutine, we make it possible for subclasses of our "Package::Counter" module +to replace the C<_build_counter> method. + +When a generator is called, it is passed four parameters: + +=over + +=item * the invocant on which the exporter was called + +=item * the name of the export being generated (not the name it's being installed as) + +=item * the arguments supplied for the routine + +=item * the collection of generic arguments + +=back + +The fourth item is the last major feature that hasn't been covered. + +=head2 Argument Collectors + +Sometimes you will want to accept arguments once that can then be available to +any subroutine that you're going to export. To do this, you specify +collectors, like this: + + package Menu::Airline + use Sub::Exporter -setup => { + exports => ... , + groups => ... , + collectors => [ qw(allergies ethics) ], + }; + +Collectors look like normal exports in the import call, but they don't do +anything but collect data which can later be passed to generators. If the +module was used like this: + + use Menu::Airline allergies => [ qw(peanuts) ], ethics => [ qw(vegan) ]; + +...the consumer would get a salad. Also, all the generators would be passed, +as their fourth argument, something like this: + + { allerges => [ qw(peanuts) ], ethics => [ qw(vegan) ] } + +Generators may have arguments in their definition, as well. These must be code +refs that perform validation of the collected values. They are passed the +collection value and may return true or false. If they return false, the +exporter will throw an exception. + +=head2 Generating Many Routines in One Scope + +Sometimes it's useful to have multiple routines generated in one scope. This +way they can share lexical data which is otherwise unavailable. To do this, +you can supply a generator for a group which returns a hashref of names and +code references. This generator is passed all the usual data, and the group +may receive the usual C<-prefix> or C<-suffix> arguments. + +=head1 SEE ALSO + +=over 4 + +=item * + +L<Sub::Exporter> for complete documentation and references to other exporters + +=back + +=head1 AUTHOR + +Ricardo Signes <rjbs@cpan.org> + +=head1 COPYRIGHT AND LICENSE + +This software is copyright (c) 2007 by Ricardo Signes. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut |