NAME Dispatch::Fu - Provides a reduction based approach to given/when or variable dispatch
SYNOPSIS
use strict;
use warnings;
use Dispatch::Fu; # exports 'dispatch' and 'on', which are needed
my $input_ref = [qw/1 2 3 4 5/];
my $bucket = dispatch {
my $_input_ref = shift; # <~ input reference
return ( scalar @$_input_ref > 5 ) # <~ return a string that must be
? q{bucket5} # defined below using the 'on'
: sprintf qq{bucket%d}, scalar @$_input_ref; # keyword, this i
}
$input_ref, # <~ input reference, SCALAR passed to dispatch BLOCK
on bucket0 => sub { print qq{bucket 0\n}; 0 }, # <~ if dispatch returns 'bucket0', run this CODE
on bucket1 => sub { print qq{bucket 1\n}; 1 }, # <~ if dispatch returns 'bucket1', run this CODE
on bucket2 => sub { print qq{bucket 2\n}; 2 }, # ...
on bucket3 => sub { print qq{bucket 3\n}; 3 }, # ... ... ... ...
on bucket4 => sub { print qq{bucket 4\n}; 4 }, # ...
on bucket5 => sub { print qq{bucket 5\n}; 5 }; # <~ if dispatch returns 'bucket5', run this CODE
DESCRIPTION
Dispatch::Fu
provide an idomatic and succinct way to organize a HASH
-based dispatch table.
The Problem
This can be done easily when dispatch may occur on a single variable that may be one or more static strings that are suitable to serve also as HASH
keys. For example,
my $action = get_action();
my $dispatch = {
do_dis => sub { ... },
do_dat => sub { ... }.
do_dese => sub { ... },
do_dose => sub { ... },
do_default => sub { ... },
};
if ($action or not exists $dispatch->{$action}) {
$action = q{do_default};
}
my $results = $dispatch->{$action}->();
But this nice situation breaks down if $action
is a value that is not suitable as as a HASH
key, is a range of values, or a single variable $action
is not sufficient to determine what action to dispatch. Dispatch::Fu
solves this problem.
The Solution
Dispatch::Fu
solves this problem buy providing a Perlish and idiomatic structure for computing a static key from an arbitrarily defined algorithm written by the developer using this module. This static key that is computed is then used to do to dispatch the anonyous subroutine explicitly defined but that key.
The simple ideal case can be mostly replicated below:
my $results = dispatch {
my $_action = shift;
return $_action;
},
$action,
on do_dis => sub { ... },
on do_dat => sub { ... },
on do_dese => sub { ... }.
on do_dose => sub { ... };
The one difference here is, if $action
is defined but not accounted for using the on
keyword, then dispatch
will throw an exception via die
. Certainly any logic meant to deal with the value (or lack thereof) of $action
should be handled in the dispatch
BLOCK.
USAGE
The developer using this module defines how to boil down the provided REF
into a single, static string. It can be described as a reduction operation or, maybe even a classification. The author tends to use the term buckets, because the dispatch
function decides what bucket (or case) the provided set of input falls into. It's best to play with the module rather than try to really understand it from this description.
For more working examples, look at the tests in the ./t
directory. It should quickly become apparent how to use this method and what it's for by trying it out.
dispatch
BLOCK-
BLOCK is required, and is coerced to be an anonymous subroutine that is passed a single scalar reference; this reference can be a single value or point to anything a Perl scalar reference can point to. It's the single point of entry for input.
dispatch { my ($ref) = @_; # there is only one parameter, but can a reference to anything my $key = q{default}; # initiate the default key to use, 'default' by convention not required ... # compute $key return $key; # key must be limited to the set of keys added with C<on> }, ...
It must return a static string, and that string should be one of the keys added using the
on
keyword. REF
-
This is the scalar reference that contains all the stuff to be used in the
dispatch
BLOCK. In the example above it is,$bar
.my $_ref = [qw/foo bar baz 1 3 4 5/]; dispatch { my ($ref) = @_; # there is only one parameter, but can a reference to anything my $key = q{default}; # initiate the default key to use, 'default' by convention not required ... # compute $key return $key; # key must be limited to the set of keys added with C<on> }, $_ref, # <~ the single scalar reference to be passed to the C<dispatch> BLOCK ...
on
-
This keyword builds up the dispatch table. It consists of a static string and a subroutine reference. In order for this to work for you, the
dispatch
BLOCK must return strictly only the keys that are defined viaon
.my $input_ref = [qw/foo bar baz 1 3 4 5/]; dispatch { my ($ref) = @_; # there is only one parameter, but can a reference to anything my $key = q{default}; # initiate the default key to use, 'default' by convention not required ... # compute $key return $key; # key must be limited to the set of keys added with C<on> }, $_input_ref, # <~ the single scalar reference to be passed to the C<dispatch> BLOCK on q{default} => sub {...}, on q{key1} => sub {...}, on q{key2} => sub {...}, on q{key3} => sub {...}, on q{key4} => sub {...}, on q{key5} => sub {...}; # <~ last line of the construct must end with a semicolon, like all Perl statements
Note: Currently, there is no way to specific the input parameters into the subroutine reference that is added by each
on
statement. This means that the subroutine refs are to be treated as wrappers that access the current scope. This provides maximum flexibility and allows one to manage what happens in eachon
case more explicitly.For example,
my $input_ref = [qw/foo bar baz 1 3 4 5/]; dispatch { my ($ref) = @_; my $key = q{default}; ... return $key; }, $_input_ref, on q{default} => sub { do_default($input_ref) }, on q{key1} => sub { do_key1(input => $input_ref) }, on q{key2} => sub { do_key2(qw/some other inputs entirely/) };
AUTHOR
O. ODLER 558 <oodler@cpan.org>.
LICENSE AND COPYRIGHT
Same as Perl.