NAME
   Sub::MultiMethod - yet another implementation of multimethods

SYNOPSIS
   How to generate JSON (albeit with very naive string quoting) using
   multimethods:

     use v5.12;
     use strict;
     use warnings;

     package My::JSON {
       use Moo;
       use Sub::MultiMethod qw(multimethod);
       use Types::Standard -types;

       multimethod stringify => (
         signature => [ Undef ],
         code      => sub {
           my ($self, $undef) = (shift, @_);
           'null';
         },
       );

       multimethod stringify => (
         signature => [ ScalarRef[Bool] ],
         code      => sub {
           my ($self, $bool) = (shift, @_);
           $$bool ? 'true' : 'false';
         },
       );

       multimethod stringify => (
         alias     => "stringify_str",
         signature => [ Str ],
         code      => sub {
           my ($self, $str) = (shift, @_);
           sprintf(q<"%s">, quotemeta($str));
         },
       );

       multimethod stringify => (
         signature => [ Num ],
         code      => sub {
           my ($self, $n) = (shift, @_);
           $n;
         },
       );

       multimethod stringify => (
         signature => [ ArrayRef ],
         code      => sub {
           my ($self, $arr) = (shift, @_);
           sprintf(
             q<[%s]>,
             join(q<,>, map($self->stringify($_), @$arr))
           );
         },
       );

       multimethod stringify => (
         signature => [ HashRef ],
         code      => sub {
           my ($self, $hash) = (shift, @_);
           sprintf(
             q<{%s}>,
             join(
               q<,>,
               map sprintf(
                 q<%s:%s>,
                 $self->stringify_str($_),
                 $self->stringify($hash->{$_})
               ), sort keys %$hash,
             )
           );
         },
       );
     }

     my $json = My::JSON->new;

     say $json->stringify({
       foo => 123,
       bar => [1,2,3],
       baz => \1,
       quux => { xyzzy => 666 },
     });

DESCRIPTION
   Sub::Multimethod focusses on implementing the dispatching of multimethods
   well and is less concerned with providing a nice syntax for setting them
   up. That said, the syntax provided is inspired by Moose's `has` keyword
   and hopefully not entirely horrible.

   Sub::MultiMethod has much smarter dispatching than Kavorka, but the
   tradeoff is that this is a little slower. Overall, for the JSON example in
   the SYNOPSIS, Kavorka is about twice as fast. (But with Kavorka, it would
   quote the numbers in the output because numbers are a type of string, and
   that was declared first!)

 Functions
   Sub::MultiMethod exports nothing by default. You can import the functions
   you want by listing them in the `use` statement:

     use Sub::MultiMethod "multimethod";

   You can rename functions:

     use Sub::MultiMethod "multimethod" => { -as => "mm" };

   You can import everything using `-all`:

     use Sub::MultiMethod -all;

   Sub::MultiMethod also offers an API for setting up multimethods for a
   class, in which case, you don't need to import anything.

  `multimethod $name => %spec`
   The following options are supported in the specification for the
   multimethod.

   `named` *(Bool)*
       Optional, defaults to false.

       Indicates whether this candidate uses named parameters. The default is
       positional parameters.

   `signature` *(ArrayRef|CodeRef)*
       Required.

       For positional parameters, an ordered list of type constraints
       suitable for passing to `compile` from Type::Params.

         signature => [ Str, RegexpRef, Optional[FileHandle] ],

       For named parameters, a list suitable for passing to
       `compile_named_oo`.

         signature => [
           prefix  => Str,
           match   => RegexpRef,
           output  => FileHandle, { default => sub { \*STDOUT } },
         ],

       Sub::MultiMethods is designed to handle multi *methods*, so $self at
       the start of all signatures is implied.

       `signature` *may* be a coderef instead, which should die if it gets
       passed a @_ that it cannot handle, or return @_ (perhaps after some
       processing) if it is successful. Using coderef signatures may make
       deciding which candidate to dispatch to more difficult though, in
       cases where more than one candidate matches the given parameters.

   `code` *(CodeRef)*
       Required.

       The sub to dispatch to. It will receive parameters in @_ as you would
       expect, but these parameters have been passed through the signature
       already, so will have had defaults and coercions applied.

       An example for positional parameters:

         code => sub {
           my ($self, $prefix, $match, $output) = (shift, @_);
           print {$output} $prefix;
           ...;
         },

       An example for named parameters:

         code => sub {
           my ($self, $arg) = (shift, @_);
           print {$arg->output} $arg->prefix;
           ...;
         },

       Note that $arg is an object with methods for each named parameter.

   `alias` *(Str|ArrayRef[Str])*
       Optional.

       Installs an alias for the candidate, bypassing multimethod dispatch.
       (But not bypassing the checks, coercions, and defaults in the
       signature!)

   `method` *(Int)*
       Optional, defaults to 1.

       Indicates whether the multimethod should be treated as a method (i.e.
       with an implied $self). Defaults to true, but `method => 0` can be
       given if you want multifuncs with no invocant.

       Multisubs where some candidates are methods and others are non-methods
       are not currently supported! (And probably never will be.)

       (Yes, this is technically an integer rather than a boolean. This
       allows for subs to have, say, two logical invocants. For example, in
       Catalyst, you might want to treat the context object as a second
       invocant.)

   `score` *(Int)*
       Optional.

       Overrides the constrainedness score calculated as described in the
       dispatch technique. Most scores calculated that way will typically
       between 0 and 100. Setting a score manually to something very high
       (e.g. 9999) will pretty much guarantee that it gets chosen over other
       candidates when multiple signatures match. Setting it to something low
       (e.g. -1) will mean it gets avoided.

   `no_dispatcher` *(Bool)*
       Optional. Defaults to true in roles, false otherwise.

       If set to true, Sub::MultiMethods will register the candidate method
       but won't install a dispatcher. You should mostly not worry about this
       and accept the default.

  `monomethod $name => %spec`
   As a convenience, you can use Sub::MultiMethod to install normal methods.
   Why do this instead of using Perl's plain old `sub` keyword? Well, it
   gives you the same signature checking.

   Supports the following options:

   `named` *(Bool)*
   `signature` *(ArrayRef|CodeRef)*
   `code` *(CodeRef)*
   `method` *(Int)*

   `monomethod($name, %spec)` is basically just a shortcut for
   `multimethod(undef, alias => $name, %spec)` though with error messages
   which don't mention it being an alias.

  `multimethods_from_roles`
   This function is exported for compatibility with older versions of
   Sub::MultiMethod, but in recent versions does nothing.

 Dispatch Technique
   When a multimethod is called, a list of packages to inspect for candidates
   is obtained by crawling @ISA. (For multifuncs, @ISA is ignored.)

   All candidates for the invoking class and all parent classes are
   considered.

   If any parent class includes a mono-method (i.e. not a multimethod) of the
   same name as this multimethod, then it is considered to have override any
   candidates further along the @ISA chain. (With multiple inheritance, this
   could get confusing though!) Those further candidates will not be
   considered, however the mono-method will be considered to be a candidate,
   albeit one with a very low score. (See scoring later.)

   Any candidates where it is clear they will not match based on parameter
   count will be discarded immediately.

   After that, the signatures of each are tried. If they throw an error, that
   candidate will be discarded.

   If there are still multiple possible candidates, they will be sorted based
   on how constrained they are.

   To determine how constrained they are, every type constraint in their
   signature is assigned a score. Any is 0. Defined inherits from Any, so has
   score 1. Value inherits from Defined, so has score 2. Etc. Some types
   inherit from a parent but without further constraining the parent. (For
   example, Item inherits from Any but doesn't place any additional
   constraints on values.) In these cases, the child type has the same score
   as its parent. All these scores are added together to get a single score
   for the candidate. For candidates where the signature is a coderef, this
   is essentially a zero score for the signature unless a score was specified
   explicitly.

   If multiple candidates are equally constrained, child class candidates
   beat parent class candidates; class candidates beat role candidates; and
   the candidate that was declared earlier wins.

   Method-resolution order (DFS/C3) is respected, though in Perl 5.8 under
   very contrived conditions (calling a sub as a function when it was defined
   as a method, but not passing a valid invocant as the first parameter), MRO
   may not always work correctly.

   Note that invocants are not part of the signature, so not taken into
   account when calculating scores, but because child class candidates beat
   parent class candidates, they should mostly behave as expected.

   After this, there should be one preferred candidate or none. If there is
   none, an error occurs. If there is one, that candidate is dispatched to
   using `goto` so there is no trace of Sub::MultiMethod in `caller`. It gets
   passed the result from checking the signature earlier as @_.

  Roles
   As far as I'm aware, Sub::MultiMethod is the only multimethod
   implementation that allows multimethods imported from roles to integrate
   into a class.

     use v5.12;
     use strict;
     use warnings;

     package My::RoleA {
       use Moo::Role;
       use Sub::MultiMethod qw(multimethod);
       use Types::Standard -types;

       multimethod foo => (
         signature  => [ HashRef ],
         code       => sub { return "A" },
         alias      => "foo_a",
       );
     }

     package My::RoleB {
       use Moo::Role;
       use Sub::MultiMethod qw(multimethod);
       use Types::Standard -types;

       multimethod foo => (
         signature  => [ ArrayRef ],
         code       => sub { return "B" },
       );
     }

     package My::Class {
       use Moo;
       use Sub::MultiMethod qw(multimethod);
       use Types::Standard -types;

       with qw( My::RoleA My::RoleB );

       multimethod foo => (
         signature  => [ HashRef ],
         code       => sub { return "C" },
       );
     }

     my $obj = My::Class->new;

     say $obj->foo_a( {} );  # A (alias defined in RoleA)
     say $obj->foo( [] );    # B (candidate from RoleB)
     say $obj->foo( {} );    # C (Class overrides candidate from RoleA)

   All other things being equal, candidates defined in classes should beat
   candidates imported from roles.

 API
   Sub::MultiMethod avoids cute syntax hacks because those can be added by
   third party modules. It provides an API for these modules.

   Brief note on terminology: when you define multimethods in a class, each
   possible signature+coderef is a "candidate". The method which makes the
   decision about which candidate to call is the "dispatcher". Roles will
   typically have candidates but no dispatcher. Classes will need dispatchers
   setting up for each multimethod.

   `Sub::MultiMethod->install_candidate($target, $sub_name, %spec)`
       $target is the class (package) name being installed into.

       $sub_name is the name of the method.

       %spec is the multimethod spec. If $target is a role, you probably want
       to include `no_dispatcher => 1` as part of the spec.

   `Sub::MultiMethod->install_dispatcher($target, $sub_name, $is_method)`
       $target is the class (package) name being installed into.

       $sub_name is the name of the method.

       $is_method is an integer/boolean.

       This rarely needs to be manually called as `install_candidate` will do
       it automatically.

   `Sub::MultiMethod->install_monomethod($target, $sub_name, %spec)`
       Installs a regular (non-multimethod) method into the target.

   `Sub::MultiMethod->copy_package_candidates(@sources => $target)`
       @sources is the list of packages to copy candidates from.

       $target is the class (package) name being installed into.

       Sub::MultiMethod will use Role::Hooks to automatically copy candidates
       from roles to consuming classes if your role implementation is
       supported. (Supported implementations include Role::Tiny, Role::Basic,
       Moo::Role, Moose::Role, and Mouse::Role, plus any role implementations
       that extend those. If your role implementation is something else, then
       when you consume a role into a class you may need to copy the
       candidates from the role to the class.)

   `Sub::MultiMethod->install_missing_dispatchers($target)`
       Should usually be called after `copy_package_candidates`, unless
       $target is a role.

       Again, this is unnecessary if your role implementation is supported by
       Role::Hooks.

   `Sub::MultiMethod->get_multimethods($target)`
       Returns the names of all multimethods declared for a class or role,
       not including any parent classes.

   `Sub::MultiMethod->has_multimethod_candidates($target, $method_name)`
       Indicates whether the class or role has any candidates for a
       multimethod. Does not include parent classes.

   `Sub::MultiMethod->get_multimethod_candidates($target, $method_name)`
       Returns a list of candidate spec hashrefs for the method, not
       including candidates from parent classes.

   `Sub::MultiMethod->get_all_multimethod_candidates($target, $method_name,
   $is_method)`
       Returns a list of candidate spec hashrefs for the method, including
       candidates from parent classes (unless $is_method is false, because
       non-methods shouldn't be inherited).

   `Sub::MultiMethod->known_dispatcher($coderef)`
       Returns a boolean indicating whether the coderef is known to be a
       multimethod dispatcher.

   `Sub::MultiMethod->pick_candidate(\@candidates, \@args, \@invocants)`
       Returns a list of three items: first the winning candidate from an
       array of specs, given the args and invocants, second the modified args
       after coercion has been applied, and third the modified invocants.

       This is basically how the dispatcher for a method works:

         my @invocants = splice(@_, 0, $ismethod);
         my $pkg       = __PACKAGE__;

         my $smm = 'Sub::MultiMethod';
         my @candidates =
           $smm->get_all_multimethod_candidates($pkg, $sub, $ismethod);
         my ($winner, $new_args, $new_invocants) =
           $smm->pick_candidate(\@candidates, \@_, \@invocants);

         my $coderef = $winner->{code};
         @_ = (@$new_invocants, @$new_args);
         goto $coderef;

BUGS
   Please report any bugs to
   <http://rt.cpan.org/Dist/Display.html?Queue=Sub-MultiMethod>.

SEE ALSO
   Class::Multimethods - uses Perl classes and ref types to dispatch. No
   syntax hacks but the fairly nice syntax shown in the pod relies on `use
   strict` being switched off! Need to quote a few more things otherwise.

   Class::Multimethods::Pure - similar to Class::Multimethods but with a more
   complex type system and a more complex dispatch method.

   Logic - a full declarative programming framework. Overkill if all you want
   is multimethods. Uses source filters.

   Dios - object oriented programming framework including multimethods.
   Includes a full type system and Keyword::Declare-based syntax. Pretty
   sensible dispatch technique which is almost identical to Sub::MultiMethod.
   Much much slower though, at both compile time and runtime.

   MooseX::MultiMethods - uses Moose type system and Devel::Declare-based
   syntax. Not entirely sure what the dispatching method is.

   Kavorka - I wrote this, so I'm allowed to be critical. Type::Tiny-based
   type system. Very naive dispatching; just dispatches to the first declared
   candidate that can handle it rather than trying to find the "best". It is
   fast though.

   Sub::Multi::Tiny - uses Perl attributes to declare candidates to be
   dispatched to. Pluggable dispatching, but by default uses argument count.

   Sub::Multi - syntax wrapper around Class::Multimethods::Pure?

   Sub::SmartMatch - kind of abandoned and smartmatch is generally seen as
   teh evilz these days.

AUTHOR
   Toby Inkster <[email protected]>.

COPYRIGHT AND LICENCE
   This software is copyright (c) 2020 by Toby Inkster.

   This is free software; you can redistribute it and/or modify it under the
   same terms as the Perl 5 programming language system itself.

DISCLAIMER OF WARRANTIES
   THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
   WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
   MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.