File Coverage

blib/lib/Sub/MultiMethod.pm
Criterion Covered Total %
statement 340 358 94.9
branch 115 140 82.1
condition 46 64 71.8
subroutine 51 52 98.0
pod 11 12 91.6
total 563 626 89.9


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