Algorithm-DependencySolver
view release on metacpan or search on metacpan
lib/Algorithm/DependencySolver/Traversal.pm view on Meta::CPAN
package Algorithm::DependencySolver::Traversal;
$Algorithm::DependencySolver::Traversal::VERSION = '1.01';
use Moose;
use MooseX::FollowPBP;
use MooseX::Method::Signatures;
use List::MoreUtils qw(all uniq);
use Data::Dumper;
=head1 NAME
Algorithm::DependencySolver::Traversal - A module for traversing a dependency graph
=head1 VERSION
version 1.01
=head1 SYNOPSIS
my $traversal = Algorithm::DependencySolver::Traversal->new(
Solver => $solver,
visit => sub {
my $operation = shift;
print "Visited operation: ", $operation->id, "\n";
},
);
$traversal->run;
=head1 DESCRIPTION
Given an L<Algorithm::DependencySolver::Solver.pm> object, traverses it
in such a way that upon entering a node, all of its prerequisites will
have already been entered.
=head2 Concurrency
Currently this module is I<not> thread-safe. However, it has been
design in such a way that it should be easy to allow concurrency at a
later stage, without needing to break backwards compatibility.
Note that if we allow concurrency, the C<visitable> list may be empty,
without indicating that the traversal is complete.
=head1 METHODS
=cut
has 'Solver' => (
is => 'ro',
isa => 'Algorithm::DependencySolver::Solver',
required => 1,
);
has 'visitable' => (
is => 'rw',
# isa => 'ArrayRef[String]',
default => sub { [] },
);
# indexed by $node->id; value is boolean
has 'visited' => (
is => 'ro',
# isa => 'HashRef[Bool]',
default => sub { {} },
);
has 'visit' => (
is => 'rw',
isa => 'CodeRef',
default => sub { sub { 1 } },
);
has 'choose' => (
is => 'ro',
isa => 'CodeRef',
default => sub { sub { shift } },
);
=head2 C<choose>
During the traversal, we maintain a list of nodes, C<visitable>, which
can be immediately visited. If this list is empty, the traversal is
complete.
The C<choose> function is called to decide which node is C<visitable>
to visit next. Note that C<choose> is guaranteed to be called, even if
C<visitable> is a singleton (but not if it's empty).
=cut
method choose() {
my $size = @{$self->get_visitable};
die "choose(): precondition for size failed" unless $size;
my $choice = $self->get_choose->(@{$self->get_visitable});
( run in 0.429 second using v1.01-cache-2.11-cpan-efa8479b9fe )