Class-Multimethods-Pure

 view release on metacpan or  search on metacpan

lib/Class/Multimethods/Pure.pm  view on Meta::CPAN


To enable a different core for all multimethods, set
C<$Class::Multimethods::Pure::DEFAULT_CORE> to the desired core.  For example:

    use Class::Multimethods::Pure;
    $Class::Multimethods::Pure::DEFAULT_CORE = 'DecisionTree';

(If the name given to core is not already a class, then the module will try
prepending Class::Multimethods::Pure::Method.  I suppose you could get in
trouble if you happened to have a package named Slow, DumbCache, 
DecisionTree in your program.  When in doubt, fully qualify.)

A more courteous and versatile approach is to specify the core as an
option to the method definition; i.e.:

    use Class::Multimethods::Pure foo => ('A', 'B'),
                                 -Core => 'DecisionTree',
                                  sub {...}

or:

    multi foo => ('A', 'B'), -Core => 'DecisionTree', sub {
        ...
    };

You may also set options separately from definiton, like:

    use Class::Multimethods::Pure 'foo', -Core => 'DecisionTree';

or:
 
    multi 'foo', -Core => 'DecisionTree';

which sets the core but defines no variant.

=head2 Combinator Factoring

One of the things that I find myself wanting to do most when working
with multimethods is to have combinator types.  These are types that
simply call the multimethod again for some list of aggregated objects
and perform some operation on them (like a Junction). They're easy
to make if they're by themselves.

    multi foo => ('Junction', 'Object') => sub {...}
    multi foo => ('Object', 'Junction') => sub {...}
    multi foo => ('Junction', 'Junction') => sub {...}

However, you find yourself in a major pickle if you want to have more of
them.  For instance:

    multi foo => ('Kunction', 'Object') => sub {...}
    multi foo => ('Object', 'Kunction') => sub {...}
    multi foo => ('Kunction', 'Kunction') => sub {...}

Now they're both combinators, but the module yells at you if you pass
(Kunction, Junction), because there are two methods that would satisfy
that.

The way to define precedence with these combinators is similar to the
way you define precedence in a recursive descent grammar.  You create a
cascade of empty classes at the top of your heirarchy, and derive each
of your generics from a different one of those:

    package AnyObject;
    package JunctionObject;
        use base 'AnyObject';
    package KunctionObject;
        use base 'JunctionObject';
    package Object;
        use base 'KunctionObject';
        # derive all other classes from Object
    
    package Junction;
        use base 'JunctionObject';
        ...
    package Kunction;
        use base 'KunctionObject';
        ...

Now define your multis using these:

    multi foo => ('Junction', 'JunctionObject') => {...}
    multi foo => ('JunctionObject', 'Junction') => {...}
    multi foo => ('Junction', 'Junction') => {...}
    multi foo => ('Kunction', 'KunctionObject') => {...}
    multi foo => ('KunctionObject', 'Kunction') => {...}
    multi foo => ('Kunction', 'Kunction') => {...}

Then the upper one (Junction in this case) will get threaded first,
because a Junction is not a KunctionObject, so it doesn't fit in the
latter three methods.

=head2 Extending

Class::Multimethods::Pure was written to be extended in many ways, but
with a focus on adding new types of, er, types.  Let's say you want to
add Perl 6-ish roles to the Class::Multimethods::Pure dispatcher.  You
need to do four things:

=over

=item * 

Create a class, say My::Role derived from
Class::Multimethods::Pure::Type.  

=item * 

Define the method My::Role::matches, which takes a scalar and returns
whether it is a member of that class (including subclasses, etc.).

=item *

Define the method My::Role::string, which returns a reasonable string
representation of the type, for the user's sake.

=item *

Define as many multimethod variants of "subset" as necessary, which
return whether an object which is a member of the left type implies that
it is a member of the right type.  Construct a



( run in 0.935 second using v1.01-cache-2.11-cpan-bbe5e583499 )