Add built local::lib
[catagits/Gitalist.git] / local-lib5 / lib / perl5 / Sub / Exporter / Cookbook.pod
1
2 =head1 NAME
3
4 Sub::Exporter::Cookbook - useful, demonstrative, or stupid Sub::Exporter tricks
5
6 =head1 OVERVIEW
7
8 Sub::Exporter is a fairly simple tool, and can be used to achieve some very
9 simple goals.  Its basic behaviors and their basic application (that is,
10 "traditional" exporting of routines) are described in
11 L<Sub::Exporter::Tutorial> and L<Sub::Exporter>.  This document presents
12 applications that may not be immediately obvious, or that can demonstrate how
13 certain features can be put to use (for good or evil).
14
15 =head1 THE RECIPES
16
17 =head2 Exporting Methods as Routines
18
19 With Exporter.pm, exporting methods is a non-starter.  Sub::Exporter makes it
20 simple.  By using the C<curry_method> utility provided in
21 L<Sub::Exporter::Util>, a method can be exported with the invocant built in.
22
23   package Object::Strenuous;
24
25   use Sub::Exporter::Util;
26   use Sub::Exporter -setup => {
27     exports => [ objection => curry_method('new') ],
28   };
29
30 With this configuration, the importing code may contain:
31
32   my $obj = objection("irrelevant");
33
34 ...and this will be equivalent to:
35
36   my $obj = Object::Strenuous->new("irrelevant");
37
38 The built-in invocant is determined by the invocant for the C<import> method.
39 That means that if we were to subclass Object::Strenuous as follows:
40
41   package Object::Strenuous::Repeated;
42   @ISA = 'Object::Strenuous';
43
44 ...then importing C<objection> from the subclass would build-in that subclass.
45
46 Finally, since the invocant can be an object, you can write something like
47 this:
48
49   package Cypher;
50   use Sub::Exporter -setup => {
51     exports => [ encypher => curry_method ],
52   };
53
54 with the expectation that C<import> will be called an instantiated Cypher
55 object:
56
57   BEGIN {
58     my $cypher = Cypher->new( ... );
59     $cypher->import('encypher');
60   }
61
62 Now there is a globally-available C<encypher> routine which calls the encypher
63 method on an otherwise unavailable Cypher object.
64
65 =head2 Exporting Methods as Methods
66
67 While exporting modules usually export subroutines to be called as subroutines,
68 it's easy to use Sub::Exporter to export subroutines meant to be called as
69 methods on the importing package or its objects.
70
71 Here's a trivial (and naive) example:
72
73   package Mixin::DumpObj;
74
75   use Data::Dumper;
76
77   use Sub::Exporter -setup => {
78     exports => [ qw(dump) ]
79   };
80
81   sub dump {
82     my ($self) = @_;
83     return Dumper($self);
84   }
85
86 When writing your own object class, you can then import C<dump> to be used as a
87 method, called like so:
88
89   $object->dump;
90
91 By assuming that the importing class will provide a certain interface, a
92 method-exporting module can be used as a simple plugin:
93
94   package Number::Plugin::Upto;
95   use Sub::Exporter -setup => {
96     into    => 'Number',
97     exports => [ qw(upto) ],
98     groups  => [ default => [ qw(upto) ] ],
99   };
100
101   sub upto {
102     my ($self) = @_;
103     return 1 .. abs($self->as_integer);
104   }
105
106 The C<into> line in the configuration says that this plugin will export, by
107 default, into the Number package, not into the C<use>-ing package.  It can be
108 exported anyway, though, and will work as long as the destination provides an
109 C<as_integer> method like the one it expects.  To import it to a different
110 destination, one can just write:
111
112   use Number::Plugin::Upto { into => 'Quantity' };    
113
114 =head2 Mixing-in Complex External Behavior
115
116 When exporting methods to be used as methods (see above), one very powerful
117 option is to export methods that are generated routines that maintain an
118 enclosed reference to the exporting module.  This allows a user to import a
119 single method which is implemented in terms of a complete, well-structured
120 package.
121
122 Here is a very small example:
123
124   package Data::Analyzer;
125
126   use Sub::Exporter -setup => {
127     exports => [ analyze => \'_generate_analyzer' ],
128   };
129
130   sub _generate_analyzer {
131     my ($mixin, $name, $arg, $col) = @_;
132
133     return sub {
134       my ($self) = @_;
135
136       my $values = [ $self->values ];
137
138       my $analyzer = $mixin->new($values);
139       $analyzer->perform_analysis;
140       $analyzer->aggregate_results;
141
142       return $analyzer->summary;
143     };
144   }
145
146 If imported by any package providing a C<values> method, this plugin will
147 provide a single C<analyze> method that acts as a simple interface to a more
148 complex set of behaviors.
149
150 Even more importantly, because the C<$mixin> value will be the invocant on
151 which the C<import> was actually called, one can subclass C<Data::Analyzer> and
152 replace only individual pieces of the complex behavior, making it easy to write
153 complex, subclassable toolkits with simple single points of entry for external
154 interfaces.
155
156 =head2 Exporting Constants
157
158 While Sub::Exporter isn't in the constant-exporting business, it's easy to
159 export constants by using one of its sister modules, Package::Generator.
160
161   package Important::Constants;
162  
163   use Sub::Exporter -setup => {
164     collectors => [ constants => \'_set_constants' ],
165   };
166  
167   sub _set_constants {
168     my ($class, $value, $data) = @_;
169  
170     Package::Generator->assign_symbols(
171       $data->{into},
172       [
173         MEANING_OF_LIFE => 42,
174         ONE_TRUE_BASE   => 13,
175         FACTORS         => [ 6, 9 ],
176       ],
177     );
178   }
179
180 Then, someone can write:
181
182   use Important::Constants 'constants';
183   
184   print "The factors @FACTORS produce $MEANING_OF_LIFE in $ONE_TRUE_BASE.";
185
186 (The constants must be exported via a collector, because they are effectively
187 altering the importing class in a way other than installing subroutines.)
188  
189 =head2 Altering the Importer's @ISA
190
191 It's trivial to make a collector that changes the inheritence of an importing
192 package:
193
194   use Sub::Exporter -setup => {
195     collectors => { -base => \'_make_base' },
196   };
197
198   sub _make_base {
199     my ($class, $value, $data) = @_;
200
201     my $target = $data->{into};
202     push @{"$target\::ISA"}, $class;
203   }
204
205 Then, the user of your class can write:
206
207   use Some::Class -base;
208
209 and become a subclass.  This can be quite useful in building, for example, a
210 module that helps build plugins.  We may want a few utilities imported, but we
211 also want to inherit behavior from some base plugin class;
212
213   package Framework::Util;
214
215   use Sub::Exporter -setup => {
216     exports    => [ qw(log global_config) ],
217     collectors => { _become_plugin => \'_become_plugin' },
218     groups     => [ -plugin => [ qw(log global_config _become_plugin) ]
219   };
220
221   sub _become_plugin {
222     my ($class, $value, $data) = @_;
223
224     my $target = $data->{into};
225     push @{"$target\::ISA"}, $class->plugin_base_class;
226   }
227
228 Now, you can write a plugin like this:
229
230   package Framework::Plugin::AirFreshener;
231   use Framework::Util -plugin;
232
233 =head2 Eating Exporter.pm's Brain
234
235 You probably shouldn't actually do this in production.  It's offered more as a
236 demonstration than a suggestion.
237
238  sub exporter_upgrade {
239    my ($pkg) = @_;
240    my $new_pkg = "$pkg\::UsingSubExporter";
241
242    return $new_pkg if $new_pkg->isa($pkg);
243
244    Sub::Exporter::setup_exporter({
245      as      => 'import',
246      into    => $new_pkg,
247      exports => [ @{"$pkg\::EXPORT_OK"} ],
248      groups  => {
249        %{{"$pkg\::EXPORT_TAG"},
250        default => [ @{"$pkg\::EXPORTS"} ],
251      },
252    });
253
254    @{"$new_pkg\::ISA"} = $class;
255    return $new_pkg;
256  }
257
258 This routine, given the name of an existing package configured to use
259 Exporter.pm, returns the name of a new package with a Sub::Exporter-powered
260 C<import> routine.  This lets you write:
261
262   BEGIN {
263     require Toolkit;
264     exporter_upgrade('Toolkit')->import(exported_sub => { -as => 'foo' })
265   }
266
267 If you're feeling particularly naughty, this routine could have been declared
268 in the UNIVERSAL package, meaning you could write:
269
270   BEGIN {
271     require Toolkit;
272     Toolkit->exporter_upgrade->import(exported_sub => { -as => 'foo' })
273   }
274
275 The new package will have all the same exporter configuration as the original,
276 but will support export and group renaming, including exporting into scalar
277 references.  Further, since Sub::Exporter uses C<can> to find the routine being
278 exported, the new package may be subclassed and some of its exports replaced.
279
280 =head1 AUTHOR
281
282 Ricardo SIGNES, C<< <rjbs@cpan.org> >>
283
284 =head1 COPYRIGHT
285
286 Copyright 2007, Ricardo SIGNES.  This is free software;  you can redistribute
287 it and/or modify it under the same terms as Perl itself.
288