File Coverage

blib/lib/Sub/MultiMethod.pm
Criterion Covered Total %
statement 329 357 92.1
branch 108 136 79.4
condition 44 68 64.7
subroutine 50 52 96.1
pod 11 13 84.6
total 542 626 86.5


line stmt bran cond sub pod time code
1 11     11   1161394 use 5.008001;
  11         116  
2 11     11   49 use strict;
  11         19  
  11         205  
3 11     11   42 use warnings;
  11         14  
  11         576  
4              
5              
6             our $AUTHORITY = 'cpan:TOBYINK';
7             our $VERSION = '0.909';
8              
9             use B ();
10 11     11   52 use Exporter::Shiny qw(
  11         15  
  11         248  
11 11         66 multimethod monomethod
12             multifunction monofunction
13             multimethods_from_roles
14             );
15 11     11   3653 use Role::Hooks;
  11         15770  
16 11     11   4505 use Scalar::Util qw( refaddr );
  11         49383  
  11         334  
17 11     11   80 use Type::Params ();
  11         19  
  11         454  
18 11     11   4699 use Types::Standard qw( -types -is );
  11         374764  
  11         280  
19 11     11   81  
  11         17  
  11         96  
20             *_set_subname =
21             eval { require Sub::Util; \&Sub::Util::set_subname } ||
22             eval { require Sub::Name; \&Sub::Name::subname } ||
23             do { sub { pop } } ;
24              
25             {
26             my %CANDIDATES;
27             my ($me, $target) = @_;
28             if ( not $CANDIDATES{$target} ) {
29 371     371   459 $CANDIDATES{$target} = {};
30 371 100       581 }
31 33         56 $CANDIDATES{$target};
32             }
33 371         509 }
34              
35             my ($me, $target) = @_;
36             sort keys %{ $me->_get_multimethods_ref($target) };
37             }
38 17     17 1 23  
39 17         17 my ($me, $target, $method_name) = @_;
  17         21  
40             my ( $package_key, $method_key ) = ref( $method_name )
41             ? ( '__CODE__', refaddr( $method_name ) )
42             : ( $target, $method_name );
43 351     351   457 my $mm = $me->_get_multimethods_ref( $package_key );
44 351 100       593 $mm->{$method_key} ||= [];
45             }
46              
47 351         493 my ( $me, $target, $method_name ) = ( shift, @_ );
48 351   100     869 my ( $package_key, $method_key ) = ref( $method_name )
49             ? ( '__CODE__', refaddr( $method_name ) )
50             : ( $target, $method_name );
51             my $mm = $me->_get_multimethods_ref( $package_key );
52 2     2   3 delete $mm->{$method_key};
53 2 50       5 return $me;
54             }
55            
56 2         4 my ($me, $target, $method_name) = @_;
57 2         3 @{ $me->_get_multimethod_candidates_ref($target, $method_name) };
58 2         3 }
59              
60             my ($me, $target, $method_name) = @_;
61             scalar @{ $me->_get_multimethod_candidates_ref($target, $method_name) };
62 101     101 1 147 }
63 101         122  
  101         140  
64             my ($me, $target, $method_name, $spec) = @_;
65             my $mmc = $me->_get_multimethod_candidates_ref($target, $method_name);
66             if ( @$mmc and $spec->{method} != $mmc->[0]{method} ) {
67 139     139 1 219 require Carp;
68 139         147 Carp::carp(sprintf(
  139         204  
69             "Added multimethod candidate for %s with method=>%d but expected method=>%d",
70             $method_name,
71             $spec->{method},
72 111     111   186 $mmc->[0]{method},
73 111         161 ));
74 111 50 66     284 }
75 0         0 push @$mmc, $spec;
76             $me;
77             }
78              
79             my ($me, $target, $method_name, $is_method) = @_;
80            
81 0         0 # Figure out which packages to consider when finding candidates.
82             my (@packages, $is_coderef_method);
83 111         156 if (is_Int $method_name or is_ScalarRef $method_name) {
84 111         158 @packages = '__CODE__';
85             $is_coderef_method = 1;
86             }
87             else {
88 59     59 1 147 @packages = $is_method
89             ? @{ mro::get_linear_isa($target) }
90             : $target;
91 59         70 }
92 59 100 66     252
93 11         13 my $curr_height = @packages;
94 11         11
95             # Find candidates from each package
96             my @candidates;
97             my $final_fallback = undef;
98 48 100       114 PACKAGE: while (@packages) {
  46         176  
99             my $p = shift @packages;
100             my @c;
101             my $found = $me->has_multimethod_candidates($p, $method_name);
102 59         85 if ($found) {
103             @c = $me->get_multimethod_candidates($p, $method_name);
104             }
105 59         75 elsif (not $is_coderef_method) {
106 59         71 no strict 'refs';
107 59         142 if (exists &{"$p\::$method_name"}) {
108 139         171 # We found a potential monomethod.
109 139         168 my $coderef = \&{"$p\::$method_name"};
110 139         245 if (!$me->known_dispatcher($coderef)) {
111 139 100       285 # Definite monomethod. Stop falling back.
    50          
112 84         482 $final_fallback = $coderef;
113             last PACKAGE;
114             }
115 11     11   88672 }
  11         22  
  11         12464  
116 55 100       71 @c = ();
  55         197  
117             }
118 8         11 # Record their height in case we need it later
  8         18  
119 8 50       17 $_->{height} = $curr_height for @c;
120             push @candidates, @c;
121 8         14 --$curr_height;
122 8         17 }
123            
124             # If a monomethod was found, use it as last resort
125 47         71 if (defined $final_fallback) {
126             push @candidates, {
127             signature => sub { @_ },
128 131         305 code => $final_fallback,
129 131         230 };
130 131         259 }
131            
132             return @candidates;
133             }
134 59 100       102  
135             {
136 8     8   23 my %DISPATCHERS;
137 8         34
138             my ($me, $coderef) = @_;
139             $DISPATCHERS{refaddr($coderef)};
140             }
141 59         230
142             my ($me, $coderef) = @_;
143             $DISPATCHERS{refaddr($coderef)} = 1;
144             $me;
145             }
146            
147             my ($me, $coderef) = @_;
148 31     31 1 50 $DISPATCHERS{refaddr($coderef)} = 0;
149 31         126 $me;
150             }
151             }
152              
153 23     23   44 my ($me, $name, $args, $globals) = (shift, @_);
154 23         75 return sub {
155 23         31 require Carp;
156             Carp::carp( "Calling multimethods_from_roles is no longer needed and the function will be removed in a future release. Called" );
157             };
158             }
159 0     0   0  
160 0         0 my ( $me, $name, $args, $globals ) = ( shift, @_ );
161 0         0
162             my $target = $globals->{into};
163             if ( ref $target or not defined $target ) {
164             require Carp;
165             Carp::croak( "Function $name can only be installed into a package by package name" );
166 4     4   175 }
167            
168 0     0   0 my %defaults = %{ $args->{defaults} || {} };
169 0         0 my $api_call = $args->{api_call} || 'install_candidate';
170 4         26
171             return sub {
172             my ( $sub_name, %spec ) = @_;
173             if ( $defaults{no_dispatcher} eq 'auto' ) {
174 36     36   68 $defaults{no_dispatcher} = 0+!! 'Role::Hooks'->is_role( $target );
175             }
176 36         62 $me->$api_call(
177 36 50 33     164 $target,
178 0         0 $sub_name,
179 0         0 %defaults,
180             %spec,
181             );
182 36 50       50 };
  36         142  
183 36   100     120 }
184              
185             my ( $me, $name, $args, $globals ) = ( shift, @_ );
186 51     51   15268 $args->{defaults}{no_dispatcher} = 'auto';
187 51 100       160 return $me->_generate_exported_function( $name, $args, $globals );
188 22         111 }
189              
190 51         590 my ( $me, $name, $args, $globals ) = ( shift, @_ );
191             $args->{defaults}{no_dispatcher} = 1;
192             $args->{api_call} = 'install_monomethod';
193             return $me->_generate_exported_function( $name, $args, $globals );
194             }
195              
196 36         253 my ( $me, $name, $args, $globals ) = ( shift, @_ );
197             $args->{defaults}{no_dispatcher} = 'auto';
198             $args->{defaults}{method} = 0;
199             return $me->_generate_exported_function( $name, $args, $globals );
200 22     22   54451 }
201 22         69  
202 22         68 my ( $me, $name, $args, $globals ) = ( shift, @_ );
203             $args->{defaults}{no_dispatcher} = 1;
204             $args->{defaults}{method} = 0;
205             $args->{api_call} = 'install_monomethod';
206 5     5   422 return $me->_generate_exported_function( $name, $args, $globals );
207 5         20 }
208 5         10  
209 5         18 my %keep_while_copying = qw(
210             method 1
211             declaration_order 1
212             signature 1
213 5     5   315 code 1
214 5         21 score 1
215 5         13 named 1
216 5         16 );
217             my $me = shift;
218             my (@sources) = @_;
219             my $target = pop @sources;
220 4     4   172
221 4         12 for my $source (@sources) {
222 4         9 for my $method_name ($me->get_multimethods($source)) {
223 4         10 for my $candidate ($me->get_multimethod_candidates($source, $method_name)) {
224 4         12 my %new = map {
225             $keep_while_copying{$_}
226             ? ( $_ => $candidate->{$_} )
227             : ()
228             } keys %$candidate;
229             $new{copied} = 1;
230             $me->_add_multimethod_candidate($target, $method_name, \%new);
231             }
232             }
233             }
234             }
235              
236 10     10 1 12 my $me = shift;
237 10         14 my ($target) = @_;
238 10         12
239             for my $method_name ($me->get_multimethods($target)) {
240 10         15 my ($first) = $me->get_multimethod_candidates($target, $method_name);
241 10         20 $me->install_dispatcher(
242 10         29 $target,
243             $method_name,
244 64         99 $first ? $first->{'method'} : 0,
245 321 100       507 );
246             }
247             }
248 64         87  
249 64         92 my $me = shift;
250             my ($target, $sub_name, %spec) = @_;
251            
252             $spec{alias} ||= [];
253             $spec{alias} = [$spec{alias}] if !ref $spec{alias};
254             unshift @{$spec{alias}}, $sub_name;
255            
256 7     7 1 143 $me->install_candidate($target, undef, no_dispatcher => 1, %spec, is_monomethod => 1);
257 7         18 }
258              
259 7         16 my %hooked;
260 7         12 my $DECLARATION_ORDER = 0;
261             my $me = shift;
262             my ($target, $sub_name, %spec) = @_;
263             $spec{method} = 1 unless defined $spec{method};
264 7 50       22  
265             my $is_method = $spec{method};
266            
267             $spec{declaration_order} = ++$DECLARATION_ORDER;
268            
269             $me->_add_multimethod_candidate($target, $sub_name, \%spec)
270 2     2 1 3 if defined $sub_name;
271 2         6
272             if ($spec{alias}) {
273 2   50     13 $spec{alias} = [$spec{alias}] unless is_ArrayRef $spec{alias};
274 2 50       6 my @aliases = @{$spec{alias}};
275 2         2 my $next = $spec{code} or die "NO CODE???";
  2         6  
276            
277 2         7 my ($check, @sig);
278             if (is_CodeRef $spec{signature}) {
279             $check = $spec{signature};
280             }
281             else {
282             @sig = @{$spec{signature}};
283 51     51 1 89 if (is_HashRef $sig[0] and not $sig[0]{slurpy}) {
284 51         133 my %new_opts = %{$sig[0]};
285 51 100       129 delete $new_opts{want_source};
286             delete $new_opts{want_details};
287 51         74 $sig[0] = \%new_opts;
288             }
289 51         73 }
290            
291 51 100       177 my $code = sprintf(
292             q{
293             package %s;
294 51 100       99 sub {
295 8 100       42 my @invocants = splice(@_, 0, %d);
296 8         12 $check ||= %s(@sig);
  8         21  
297 8 50       24 @_ = (@invocants, &$check);
298             goto $next;
299 8         12 }
300 8 50       29 },
301 0         0 $target,
302             $spec{method},
303             $spec{named}
304 8         11 ? 'Type::Params::compile_named_oo'
  8         18  
305 8 50 33     31 : 'Type::Params::compile',
306 0         0 );
  0         0  
307 0         0 my $coderef = do {
308 0         0 local $@;
309 0         0 eval $code or die $@,
310             };
311             for my $alias (@aliases) {
312             my $existing = do {
313             no strict 'refs';
314             exists(&{"$target\::$alias"})
315             ? \&{"$target\::$alias"}
316             : undef;
317             };
318             if ($existing) {
319             my $kind = ($spec{is_monomethod} && ($alias eq $aliases[0]))
320             ? 'Monomethod'
321             : 'Alias';
322             require Carp;
323             Carp::croak("$kind conflicts with existing method $target\::$alias, bailing out");
324             }
325             $me->_install_coderef( $target, $alias, $coderef );
326 8 50       49 }
327             }
328            
329 8         12 $me->install_dispatcher($target, $sub_name, $is_method)
330 8         12 if defined $sub_name && !$spec{no_dispatcher};
331 8 50 66 30   766
  24     2   9720  
  24         91  
  24         95194  
  16         831  
332             if ( !$hooked{$target} and 'Role::Hooks'->is_role($target) ) {
333 8         20 'Role::Hooks'->after_apply($target, sub {
334 8         13 my ($rolepkg, $consumerpkg) = @_;
335 11     11   77 $me->copy_package_candidates($rolepkg => $consumerpkg);
  11         23  
  11         4019  
336 8         40 $me->install_missing_dispatchers($consumerpkg)
337 8 100       11 unless 'Role::Hooks'->is_role($consumerpkg);
  2         7  
338             });
339             $hooked{$target}++;
340 8 100       21 }
341 2 100 66     13 }
342              
343             {
344 2         10 my %CLEANUP;
345 2         354
346             my $me = shift;
347 6         30 my ($target, $sub_name, $coderef) = @_;
348             if (is_ScalarRef $sub_name) {
349             if (is_Undef $$sub_name) {
350             _set_subname("$target\::__ANON__", $coderef);
351             bless( $coderef, $me );
352 49 100 100     206 $CLEANUP{"$coderef"} = [ $target, refaddr($sub_name) ];
353             return( $$sub_name = $coderef );
354 47 100 100     185 }
355             elsif (is_CodeRef $$sub_name or is_Object $$sub_name) {
356 10     10   2275 if ( $me->known_dispatcher($$sub_name) ) {
357 10         22 return $$sub_name;
358 10 100       22 }
359             else {
360 5         70 require Carp;
361 5         694 Carp::croak(sprintf(
362             'Sub name was a reference to an unknown coderef or object: %s',
363             $$sub_name,
364             ));
365             }
366             }
367             }
368             elsif (is_Str $sub_name) {
369 29     29   50 no strict 'refs';
370 29         58 my $qname = "$target\::$sub_name";
371 29 100       130 *$qname = _set_subname($qname, $coderef);
    50          
372 7 100 33     28 return $coderef;
    50          
373 2         12 }
374 2         3 require Carp;
375 2         11 Carp::croak(sprintf(
376 2         6 'Expected string or reference to coderef as sub name, but got: %s %s',
377             $sub_name,
378             ));
379 5 50       10 }
380 5         9
381             my $blessed_coderef = shift;
382             my ( $target, $sub_name ) = @{ $CLEANUP{"$blessed_coderef"} or [] };
383 0         0 if ( $target and $sub_name ) {
384 0         0 $blessed_coderef->_clear_multimethod_candidates_ref($target, $sub_name);
385             }
386             return;
387             }
388             }
389              
390             my $me = shift;
391             my ($target, $sub_name, $is_method) = @_;
392 11     11   80
  11         20  
  11         2199  
393 22         49 exists &mro::get_linear_isa
394 22         190 or eval { require mro }
395 22         60 or do { require MRO::Compat };
396            
397 0         0 my $existing = do {
398 0         0 no strict 'refs';
399             exists(&{"$target\::$sub_name"})
400             ? \&{"$target\::$sub_name"}
401             : undef;
402             };
403            
404             return if !defined $sub_name;
405 2     2   909
406 2 50       3 if ($existing and $me->known_dispatcher($existing)) {
  2         9  
407 2 50 33     8 return $me; # already installed
408 2         5 }
409             elsif ($existing) {
410 2         27 require Carp;
411             Carp::croak("Multimethod conflicts with monomethod $target\::$sub_name, bailing out");
412             }
413            
414             my $code = sprintf(
415 41     41 1 60 q{
416 41         64 package %s;
417             sub {
418             my $next = %s->can('dispatch');
419 0         0 @_ = (%s, %s, %s, %d, [@_]);
420 41 50 33     95 goto $next;
  0         0  
421             }
422 41         49 },
423 11     11   73 $target, # package %s
  11         31  
  11         6616  
424 41         132 B::perlstring($me), # %s->can('dispatch')
425 41 100       41 B::perlstring($me), # $_[0]
  18         42  
426             B::perlstring($target), # $_[1]
427             ref($sub_name) # $_[2]
428             ? refaddr($sub_name)
429 41 50       83 : B::perlstring("$sub_name"),
430             $is_method, # $_[3]
431 41 100 100     158 );
    100          
432 16         33
433             my $coderef = do {
434             local $@;
435 2         12 eval $code or die $@;
436 2         330 };
437            
438             $me->_install_coderef($target, $sub_name, $coderef);
439 23 100       236 $me->_mark_as_dispatcher($coderef);
440             return $coderef;
441             }
442              
443             my $me = shift;
444             my ($pkg, $method_name, $is_method, $argv) = @_;
445            
446             # Steal invocants because we don't want them to be considered
447             # as part of the signature.
448             my @invocants;
449             push @invocants, splice(@$argv, 0, $is_method);
450            
451             if ( $is_method and is_Object($invocants[0]) ) {
452             # object method; reset package search from invocant class
453             $pkg = ref($invocants[0]);
454             }
455             elsif ( $is_method and is_ClassName($invocants[0]) ) {
456             # class method; reset package search from invocant class
457             $pkg = $invocants[0];
458 23         40 }
459 23         27
460 23 50   9   1926 my ($winner, $new_argv, $new_invocants) = $me->pick_candidate(
  2         6  
  2         6  
461             [ $me->get_all_multimethod_candidates($pkg, $method_name, $is_method) ],
462             $argv,
463 23         85 \@invocants,
464 23         56 ) or do {
465 23         63 require Carp;
466             Carp::croak('Multimethod could not find candidate to dispatch to, stopped');
467             };
468            
469 78     78 0 5802 my $next = $winner->{code};
470 78         184 @_ = (@$new_invocants, @$new_argv);
471             goto $next;
472             }
473              
474 78         134 # Type which when given \@_ determines if it could potentially
475 61         1178 # be named parameters.
476             #
477 61 100 100     325 my $Named = CycleTuple->of(Str, Any) | Tuple->of(HashRef);
    100 100        
478              
479 41         82 my $me = shift;
480             my ($candidates, $argv, $invocants) = @_;
481            
482             my @remaining = @{ $candidates };
483 9         2391
484             # Compile signatures into something useful. (Cached.)
485             #
486            
487             for my $candidate (@remaining) {
488             next if $candidate->{compiled};
489             if (is_CodeRef $candidate->{signature}) {
490 63 100       220 $candidate->{compiled}{closure} = $candidate->{signature};
491 7         31 $candidate->{compiled}{min_args} = 0;
492 9         2839 $candidate->{compiled}{max_args} = undef;
493             }
494             else {
495 62         143 my @sig = @{ $candidate->{signature} };
496 62         134 my $opt = (is_HashRef $sig[0] and not $sig[0]{slurpy})
497 63         2847 ? shift(@sig)
498             : {};
499             $opt->{want_details} = 1;
500            
501             $candidate->{compiled} = $candidate->{named}
502             ? Type::Params::compile_named_oo($opt, @sig)
503             : Type::Params::compile($opt, @sig);
504            
505             $candidate->{compiled}{_pure_named} = $candidate->{named};
506 66     61 1 112 delete $candidate->{compiled}{_pure_named}
507 66         100 if $opt->{head} || $opt->{tail};
508             }
509 61         723 }
  61         112  
510            
511             # Weed out signatures that cannot match because of
512             # argument count.
513             #
514 61         92
515 372 100       621 my $argc = @$argv;
516 87 100       259 my $argv_maybe_named = $Named->check($argv);
517 8         18
518 8         13 @remaining = grep {
519 8         14 my $candidate = $_;
520             if ($candidate->{compiled}{_pure_named} && !$argv_maybe_named) {
521             0;
522 79         98 }
  79         196  
523             elsif (defined $candidate->{compiled}{min_args} and $candidate->{compiled}{min_args} > $argc) {
524 79 100 66     291 0;
525             }
526 79         133 elsif (defined $candidate->{compiled}{max_args} and $candidate->{compiled}{max_args} < $argc) {
527             0;
528             }
529 79 100       245 else {
530             1;
531             }
532 79         368704 } @remaining;
533            
534 79 100 66     482
535             # Weed out signatures that cannot match because
536             # they fail type checks, etc
537             #
538            
539             my %returns;
540            
541             @remaining = grep {
542 59         81 my $code = $_->{compiled}{closure};
543 59         237 eval {
544             $returns{"$code"} = [ $code->(@$argv) ];
545             1;
546 59         6374 };
  372         358  
547 372 50 33     1518 } @remaining;
    100 66        
    100 100        
548 0         0
549             # Various techniques to cope with @remaining > 1...
550             #
551 7         15
552             if (@remaining > 1) {
553             no warnings qw(uninitialized numeric);
554 2         4 # Calculate signature constrainedness score. (Cached.)
555             for my $candidate (@remaining) {
556             next if defined $candidate->{score};
557 363         498 my $sum = 0;
558             if (is_ArrayRef $candidate->{signature}) {
559             foreach my $type (@{ $candidate->{signature} }) {
560             next unless is_Object $type;
561             my @real_parents = grep !$_->_is_null_constraint, $type, $type->parents;
562             $sum += @real_parents;
563             }
564             }
565             $candidate->{score} = $sum;
566 59         75 }
567             # Only keep those with (equal) highest score
568             @remaining = sort { $b->{score} <=> $a->{score} } @remaining;
569 59         75 my $max_score = $remaining[0]->{score};
  363         48480  
570 363         466 @remaining = grep { $_->{score} == $max_score } @remaining;
571 363         675 }
572 108         1103
573             if (@remaining > 1) {
574             # Only keep those from the most derived class
575             no warnings qw(uninitialized numeric);
576             @remaining = sort { $b->{height} <=> $a->{height} } @remaining;
577             my $max_score = $remaining[0]->{height};
578             @remaining = grep { $_->{height} == $max_score } @remaining;
579 59 100       9532 }
580 11     11   79
  11         23  
  11         1875  
581             if (@remaining > 1) {
582 28         56 # Only keep those from the most non-role-like packages
583 80 100       156 no warnings qw(uninitialized numeric);
584 37         46 @remaining = sort { $a->{copied} <=> $b->{copied} } @remaining;
585 37 100       97 my $min_score = $remaining[0]->{copied};
586 33         39 @remaining = grep { $_->{copied} == $min_score } @remaining;
  33         67  
587 48 50       88 }
588 48         91
589 48         2440 if (@remaining > 1) {
590             # Argh! Still got multiple candidates! Just choose whichever
591             # was declared first...
592 37         106 no warnings qw(uninitialized numeric);
593             @remaining = sort { $a->{declaration_order} <=> $b->{declaration_order} } @remaining;
594             @remaining = ($remaining[0]);
595 28         91 }
  90         134  
596 28         37
597 28         47 # This is filled in each call. Clean it up, just in case.
  80         134  
598             delete $_->{height} for @$candidates;
599            
600 59 100       116 wantarray or die 'MUST BE CALLED IN LIST CONTEXT';
601            
602 11     11   83 return unless @remaining;
  11         20  
  11         745  
603 10         21
  28         39  
604 10         15 my $sig_code = $remaining[0]{compiled}{closure};
605 10         12 return ( $remaining[0], $returns{"$sig_code"}, $invocants||[] );
  29         48  
606             }
607              
608 59 100       114 no warnings qw(uninitialized numeric);
609             my $candidate = shift;
610 11     11   60 my $types_etc = join ",", map "$_", @{$candidate->{signature}};
  11         58  
  11         815  
611 5         10 my $r = sprintf('%s:%s', $candidate->{named} ? 'NAMED' : 'POSITIONAL', $types_etc);
  23         32  
612 5         8 $r .= sprintf('{score:%d+%d}', $candidate->{score}, $candidate->{height})
613 5         10 if defined($candidate->{score})||defined($candidate->{height});
  19         29  
614             return $r;
615             }
616 59 100       110  
617             1;
618              
619 11     11   71  
  11         14  
  11         2250  
620 4         8 =pod
  22         26  
621 4         9  
622             =encoding utf-8
623              
624             =head1 NAME
625 59         206  
626             Sub::MultiMethod - yet another implementation of multimethods
627 59 50       105  
628             =head1 SYNOPSIS
629 59 100       108  
630             How to generate JSON (albeit with very naive string quoting) using
631 56         89 multimethods:
632 56   50     274  
633             use v5.20;
634             use strict;
635             use warnings;
636 11     11   67 use experimental 'signatures';
  11         25  
  11         1732  
637 0     4 0 0
638 0         0 package My::JSON {
  0         0  
639 0 0       0 use Moo;
640             use Sub::MultiMethod qw(multimethod);
641 0 0 0     0 use Types::Standard -types;
642 0         0
643             multimethod stringify => (
644             signature => [ Undef ],
645             code => sub ( $self, $undef ) {
646             return 'null';
647             },
648             );
649            
650             multimethod stringify => (
651             signature => [ ScalarRef[Bool] ],
652             code => sub ( $self, $bool ) {
653             return $$bool ? 'true' : 'false';
654             },
655             );
656            
657             multimethod stringify => (
658             alias => "stringify_str",
659             signature => [ Str ],
660             code => sub ( $self, $str ) {
661             return sprintf( q<"%s">, quotemeta($str) );
662             },
663             );
664            
665             multimethod stringify => (
666             signature => [ Num ],
667             code => sub ( $self, $n ) {
668             return $n;
669             },
670             );
671            
672             multimethod stringify => (
673             signature => [ ArrayRef ],
674             code => sub ( $self, $arr ) {
675             return sprintf(
676             q<[%s]>,
677             join( q<,>, map( $self->stringify($_), @$arr ) )
678             );
679             },
680             );
681            
682             multimethod stringify => (
683             signature => [ HashRef ],
684             code => sub ( $self, $hash ) {
685             return sprintf(
686             q<{%s}>,
687             join(
688             q<,>,
689             map sprintf(
690             q<%s:%s>,
691             $self->stringify_str($_),
692             $self->stringify( $hash->{$_} )
693             ), sort keys %$hash,
694             )
695             );
696             },
697             );
698             }
699            
700             my $json = My::JSON->new;
701            
702             say $json->stringify( {
703             foo => 123,
704             bar => [ 1, 2, 3 ],
705             baz => \1,
706             quux => { xyzzy => 666 },
707             } );
708              
709             While this example requires Perl 5.20+, Sub::MultiMethod is tested and works
710             on Perl 5.8.1 and above.
711              
712             =head1 DESCRIPTION
713              
714             Sub::Multimethod focusses on implementing the dispatching of multimethods
715             well and is less concerned with providing a nice syntax for setting them
716             up. That said, the syntax provided is inspired by Moose's C<has> keyword
717             and hopefully not entirely horrible.
718              
719             Sub::MultiMethod has much smarter dispatching than L<Kavorka>, but the
720             tradeoff is that this is a little slower. Overall, for the JSON example
721             in the SYNOPSIS, Kavorka is about twice as fast. (But with Kavorka, it
722             would quote the numbers in the output because numbers are a type of string,
723             and that was declared first!)
724              
725             =head2 Functions
726              
727             Sub::MultiMethod exports nothing by default. You can import the functions
728             you want by listing them in the C<use> statement:
729              
730             use Sub::MultiMethod "multimethod";
731              
732             You can rename functions:
733              
734             use Sub::MultiMethod "multimethod" => { -as => "mm" };
735              
736             You can import everything using C<< -all >>:
737              
738             use Sub::MultiMethod -all;
739              
740             Sub::MultiMethod also offers an API for setting up multimethods for a
741             class, in which case, you don't need to import anything.
742              
743             =head3 C<< multimethod $name => %spec >>
744              
745             The following options are supported in the specification for the
746             multimethod.
747              
748             =over
749              
750             =item C<< named >> I<< (Bool) >>
751              
752             Optional, defaults to false.
753              
754             Indicates whether this candidate uses named parameters. The default is
755             positional parameters.
756              
757             =item C<< signature >> I<< (ArrayRef|CodeRef) >>
758              
759             Required.
760              
761             For positional parameters, an ordered list of type constraints suitable
762             for passing to C<compile> from L<Type::Params>.
763              
764             signature => [ Str, RegexpRef, Optional[FileHandle] ],
765              
766             For named parameters, a list suitable for passing to C<compile_named_oo>.
767              
768             signature => [
769             prefix => Str,
770             match => RegexpRef,
771             output => FileHandle, { default => sub { \*STDOUT } },
772             ],
773              
774             Sub::MultiMethods is designed to handle multi I<methods>, so C<< $self >>
775             at the start of all signatures is implied.
776              
777             C<signature> I<may> be a coderef instead, which should die if it gets
778             passed a C<< @_ >> that it cannot handle, or return C<< @_ >> (perhaps
779             after some processing) if it is successful. Using coderef signatures
780             may make deciding which candidate to dispatch to more difficult though,
781             in cases where more than one candidate matches the given parameters.
782              
783             =item C<< code >> I<< (CodeRef) >>
784              
785             Required.
786              
787             The sub to dispatch to. It will receive parameters in C<< @_ >> as you
788             would expect, but these parameters have been passed through the signature
789             already, so will have had defaults and coercions applied.
790              
791             An example for positional parameters:
792              
793             code => sub ( $self, $prefix, $match, $output ) {
794             print { $output } $prefix;
795             ...;
796             },
797              
798             An example for named parameters:
799              
800             code => sub ( $self, $arg ) {
801             print { $arg->output } $arg->prefix;
802             ...;
803             },
804              
805             Note that C<< $arg >> is an object with methods for each named parameter.
806              
807             Corresponding examples for older versions of Perl without signature support.
808              
809             code => sub {
810             my ( $self, $prefix, $match, $output ) = @_;
811             print { $output } $prefix;
812             ...;
813             },
814              
815             And:
816              
817             code => sub {
818             my ( $self, $arg ) = @_;
819             print { $arg->output } $arg->prefix;
820             ...;
821             },
822              
823             =item C<< alias >> I<< (Str|ArrayRef[Str]) >>
824              
825             Optional.
826              
827             Installs an alias for the candidate, bypassing multimethod dispatch. (But not
828             bypassing the checks, coercions, and defaults in the signature!)
829              
830             =item C<< method >> I<< (Int) >>
831              
832             Optional, defaults to 1.
833              
834             Indicates whether the multimethod should be treated as a method (i.e. with an
835             implied C<< $self >>). Defaults to true, but C<< method => 0 >> can be
836             given if you want multifuncs with no invocant.
837              
838             Multisubs where some candidates are methods and others are non-methods are
839             not currently supported! (And probably never will be.)
840              
841             (Yes, this is technically an integer rather than a boolean. This allows
842             for subs to have, say, two logical invocants. For example, in Catalyst,
843             you might want to treat the context object as a second invocant.)
844              
845             =item C<< score >> I<< (Int) >>
846              
847             Optional.
848              
849             Overrides the constrainedness score calculated as described in the dispatch
850             technique. Most scores calculated that way will typically between 0 and 100.
851             Setting a score manually to something very high (e.g. 9999) will pretty much
852             guarantee that it gets chosen over other candidates when multiple signatures
853             match. Setting it to something low (e.g. -1) will mean it gets avoided.
854              
855             =item C<< no_dispatcher >> I<< (Bool) >>
856              
857             Optional. Defaults to true in roles, false otherwise.
858              
859             If set to true, Sub::MultiMethods will register the candidate method
860             but won't install a dispatcher. You should mostly not worry about this
861             and accept the default.
862              
863             =back
864              
865             =head3 C<< monomethod $name => %spec >>
866              
867             As a convenience, you can use Sub::MultiMethod to install normal methods.
868             Why do this instead of using Perl's plain old C<sub> keyword? Well, it gives
869             you the same signature checking.
870              
871             Supports the following options:
872              
873             =over
874              
875             =item C<< named >> I<< (Bool) >>
876              
877             =item C<< signature >> I<< (ArrayRef|CodeRef) >>
878              
879             =item C<< code >> I<< (CodeRef) >>
880              
881             =item C<< method >> I<< (Int) >>
882              
883             =back
884              
885             C<< monomethod($name, %spec) >> is basically just a shortcut for
886             C<< multimethod(undef, alias => $name, %spec) >> though with error
887             messages which don't mention it being an alias.
888              
889             =head3 C<< multifunction $name => %spec >>
890              
891             Like C<multimethod> but defaults to C<< method => 0 >>.
892              
893             =head3 C<< monofunction $name => %spec >>
894              
895             Like C<monomethod> but defaults to C<< method => 0 >>.
896              
897             =head2 Dispatch Technique
898              
899             When a multimethod is called, a list of packages to inspect for candidates
900             is obtained by crawling C<< @ISA >>. (For multifuncs, C<< @ISA >> is ignored.)
901              
902             All candidates for the invoking class and all parent classes are considered.
903              
904             If any parent class includes a mono-method (i.e. not a multimethod) of the
905             same name as this multimethod, then it is considered to have override any
906             candidates further along the C<< @ISA >> chain. (With multiple inheritance,
907             this could get confusing though!) Those further candidates will not be
908             considered, however the mono-method will be considered to be a candidate,
909             albeit one with a very low score. (See scoring later.)
910              
911             Any candidates where it is clear they will not match based on parameter
912             count will be discarded immediately.
913              
914             After that, the signatures of each are tried. If they throw an error, that
915             candidate will be discarded.
916              
917             If there are still multiple possible candidates, they will be sorted based
918             on how constrained they are.
919              
920             To determine how constrained they are, every type constraint in their
921             signature is assigned a score. B<Any> is 0. B<Defined> inherits from
922             B<Any>, so has score 1. B<Value> inherits from B<Defined>, so has score 2.
923             Etc. Some types inherit from a parent but without further constraining
924             the parent. (For example, B<Item> inherits from B<Any> but doesn't place
925             any additional constraints on values.) In these cases, the child type
926             has the same score as its parent. All these scores are added together
927             to get a single score for the candidate. For candidates where the
928             signature is a coderef, this is essentially a zero score for the
929             signature unless a score was specified explicitly.
930              
931             If multiple candidates are equally constrained, child class candidates
932             beat parent class candidates; class candidates beat role candidates;
933             and the candidate that was declared earlier wins.
934              
935             Method-resolution order (DFS/C3) is respected, though in Perl 5.8 under
936             very contrived conditions (calling a sub as a function when it was
937             defined as a method, but not passing a valid invocant as the first
938             parameter), MRO may not always work correctly.
939              
940             Note that invocants are not part of the signature, so not taken into
941             account when calculating scores, but because child class candidates
942             beat parent class candidates, they should mostly behave as expected.
943              
944             After this, there should be one preferred candidate or none. If there is
945             none, an error occurs. If there is one, that candidate is dispatched to
946             using C<goto> so there is no trace of Sub::MultiMethod in C<caller>. It
947             gets passed the result from checking the signature earlier as C<< @_ >>.
948              
949             =head3 Roles
950              
951             As far as I'm aware, Sub::MultiMethod is the only multimethod implementation
952             that allows multimethods imported from roles to integrate into a class.
953              
954             use v5.12;
955             use strict;
956             use warnings;
957            
958             package My::RoleA {
959             use Moo::Role;
960             use Sub::MultiMethod qw(multimethod);
961             use Types::Standard -types;
962            
963             multimethod foo => (
964             signature => [ HashRef ],
965             code => sub { return "A" },
966             alias => "foo_a",
967             );
968             }
969            
970             package My::RoleB {
971             use Moo::Role;
972             use Sub::MultiMethod qw(multimethod);
973             use Types::Standard -types;
974            
975             multimethod foo => (
976             signature => [ ArrayRef ],
977             code => sub { return "B" },
978             );
979             }
980            
981             package My::Class {
982             use Moo;
983             use Sub::MultiMethod qw(multimethod);
984             use Types::Standard -types;
985            
986             with qw( My::RoleA My::RoleB );
987            
988             multimethod foo => (
989             signature => [ HashRef ],
990             code => sub { return "C" },
991             );
992             }
993            
994             my $obj = My::Class->new;
995            
996             say $obj->foo_a( {} ); # A (alias defined in RoleA)
997             say $obj->foo( [] ); # B (candidate from RoleB)
998             say $obj->foo( {} ); # C (Class overrides candidate from RoleA)
999              
1000             All other things being equal, candidates defined in classes should
1001             beat candidates imported from roles.
1002              
1003             =head2 CodeRef multimethods
1004              
1005             The C<< $name >> of a multimethod may be a scalarref, in which case
1006             C<multimethod> will install the multimethod as a coderef into the
1007             scalar referred to. Example:
1008              
1009             my ($coderef, $otherref);
1010            
1011             multimethod \$coderef => (
1012             method => 0,
1013             signature => [ ArrayRef ],
1014             code => sub { say "It's an arrayref!" },
1015             );
1016            
1017             multimethod \$coderef => (
1018             method => 0,
1019             alias => \$otherref,
1020             signature => [ HashRef ],
1021             code => sub { say "It's a hashref!" },
1022             );
1023            
1024             $coderef->( [] );
1025             $coderef->( {} );
1026            
1027             $otherref->( {} );
1028              
1029             The C<< $coderef >> and C<< $otherref >> variables will actually end up
1030             as blessed coderefs so that some tidy ups can take place in C<DESTROY>.
1031              
1032             =head2 API
1033              
1034             Sub::MultiMethod avoids cute syntax hacks because those can be added by
1035             third party modules. It provides an API for these modules.
1036              
1037             Brief note on terminology: when you define multimethods in a class,
1038             each possible signature+coderef is a "candidate". The method which
1039             makes the decision about which candidate to call is the "dispatcher".
1040             Roles will typically have candidates but no dispatcher. Classes will
1041             need dispatchers setting up for each multimethod.
1042              
1043             =over
1044              
1045             =item C<< Sub::MultiMethod->install_candidate($target, $sub_name, %spec) >>
1046              
1047             C<< $target >> is the class (package) name being installed into.
1048              
1049             C<< $sub_name >> is the name of the method.
1050              
1051             C<< %spec >> is the multimethod spec. If C<< $target >> is a role, you
1052             probably want to include C<< no_dispatcher => 1 >> as part of the spec.
1053              
1054             =item C<< Sub::MultiMethod->install_dispatcher($target, $sub_name, $is_method) >>
1055              
1056             C<< $target >> is the class (package) name being installed into.
1057              
1058             C<< $sub_name >> is the name of the method.
1059              
1060             C<< $is_method >> is an integer/boolean.
1061              
1062             This rarely needs to be manually called as C<install_candidate> will do it
1063             automatically.
1064              
1065             =item C<< Sub::MultiMethod->install_monomethod($target, $sub_name, %spec) >>
1066              
1067             Installs a regular (non-multimethod) method into the target.
1068              
1069             =item C<< Sub::MultiMethod->copy_package_candidates(@sources => $target) >>
1070              
1071             C<< @sources >> is the list of packages to copy candidates from.
1072              
1073             C<< $target >> is the class (package) name being installed into.
1074              
1075             Sub::MultiMethod will use L<Role::Hooks> to automatically copy candidates
1076             from roles to consuming classes if your role implementation is supported.
1077             (Supported implementations include Role::Tiny, Role::Basic, Moo::Role,
1078             Moose::Role, and Mouse::Role, plus any role implementations that extend
1079             those. If your role implementation is something else, then when you consume
1080             a role into a class you may need to copy the candidates from the role to
1081             the class.)
1082              
1083             =item C<< Sub::MultiMethod->install_missing_dispatchers($target) >>
1084              
1085             Should usually be called after C<copy_package_candidates>, unless
1086             C<< $target >> is a role.
1087              
1088             Again, this is unnecessary if your role implementation is supported
1089             by Role::Hooks.
1090              
1091             =item C<< Sub::MultiMethod->get_multimethods($target) >>
1092              
1093             Returns the names of all multimethods declared for a class or role,
1094             not including any parent classes.
1095              
1096             =item C<< Sub::MultiMethod->has_multimethod_candidates($target, $method_name) >>
1097              
1098             Indicates whether the class or role has any candidates for a multimethod.
1099             Does not include parent classes.
1100              
1101             =item C<< Sub::MultiMethod->get_multimethod_candidates($target, $method_name) >>
1102              
1103             Returns a list of candidate spec hashrefs for the method, not including
1104             candidates from parent classes.
1105              
1106             =item C<< Sub::MultiMethod->get_all_multimethod_candidates($target, $method_name, $is_method) >>
1107              
1108             Returns a list of candidate spec hashrefs for the method, including candidates
1109             from parent classes (unless C<< $is_method >> is false, because non-methods
1110             shouldn't be inherited).
1111              
1112             =item C<< Sub::MultiMethod->known_dispatcher($coderef) >>
1113              
1114             Returns a boolean indicating whether the coderef is known to be a multimethod
1115             dispatcher.
1116              
1117             =item C<< Sub::MultiMethod->pick_candidate(\@candidates, \@args, \@invocants) >>
1118              
1119             Returns a list of three items: first the winning candidate from an array of specs,
1120             given the args and invocants, second the modified args after coercion has been
1121             applied, and third the modified invocants.
1122              
1123             This is basically how the dispatcher for a method works:
1124              
1125             my @invocants = splice( @_, 0, $ismethod );
1126             my $pkg = __PACKAGE__;
1127            
1128             my $smm = 'Sub::MultiMethod';
1129             my @candidates =
1130             $smm->get_all_multimethod_candidates( $pkg, $sub, $ismethod );
1131             my ( $winner, $new_args, $new_invocants ) =
1132             $smm->pick_candidate( \@candidates, \@_, \@invocants );
1133            
1134             my $coderef = $winner->{code};
1135             @_ = ( @$new_invocants, @$new_args );
1136             goto $coderef;
1137              
1138             =back
1139              
1140             =head1 BUGS
1141              
1142             Please report any bugs to
1143             L<http://rt.cpan.org/Dist/Display.html?Queue=Sub-MultiMethod>.
1144              
1145             =head1 SEE ALSO
1146              
1147             L<Class::Multimethods> - uses Perl classes and ref types to dispatch.
1148             No syntax hacks but the fairly nice syntax shown in the pod relies on
1149             C<use strict> being switched off! Need to quote a few more things otherwise.
1150              
1151             L<Class::Multimethods::Pure> - similar to Class::Multimethods but with
1152             a more complex type system and a more complex dispatch method.
1153              
1154             L<Logic> - a full declarative programming framework. Overkill if all
1155             you want is multimethods. Uses source filters.
1156              
1157             L<Dios> - object oriented programming framework including multimethods.
1158             Includes a full type system and Keyword::Declare-based syntax. Pretty
1159             sensible dispatch technique which is almost identical to
1160             Sub::MultiMethod. Much much slower though, at both compile time and
1161             runtime.
1162              
1163             L<MooseX::MultiMethods> - uses Moose type system and Devel::Declare-based
1164             syntax. Not entirely sure what the dispatching method is.
1165              
1166             L<Kavorka> - I wrote this, so I'm allowed to be critical. Type::Tiny-based
1167             type system. Very naive dispatching; just dispatches to the first declared
1168             candidate that can handle it rather than trying to find the "best". It is
1169             fast though.
1170              
1171             L<Sub::Multi::Tiny> - uses Perl attributes to declare candidates to
1172             be dispatched to. Pluggable dispatching, but by default uses argument
1173             count.
1174              
1175             L<Sub::Multi> - syntax wrapper around Class::Multimethods::Pure?
1176              
1177             L<Sub::SmartMatch> - kind of abandoned and smartmatch is generally seen
1178             as teh evilz these days.
1179              
1180             =head1 AUTHOR
1181              
1182             Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
1183              
1184             =head1 COPYRIGHT AND LICENCE
1185              
1186             This software is copyright (c) 2020-2022 by Toby Inkster.
1187              
1188             This is free software; you can redistribute it and/or modify it under
1189             the same terms as the Perl 5 programming language system itself.
1190              
1191             =head1 DISCLAIMER OF WARRANTIES
1192              
1193             THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
1194             WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1195             MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1196