CPAN-Flatten
view release on metacpan or search on metacpan
lib/CPAN/Flatten/Tree.pm view on Meta::CPAN
package CPAN::Flatten::Tree;
use strict;
use warnings;
use utf8;
use Scalar::Util 'weaken';
sub new {
my $class = shift;
my %args = ref $_[0] ? %{$_[0]} : @_;
my $self = bless {
_parent => undef,
_children => [],
%args,
}, $class;
$self;
}
sub add_child {
my ($self, $node) = @_;
if ($node->{_parent}) {
require Carp;
Carp::confess("node (@{[$node->uid]}) already has a parent");
}
push @{ $self->{_children} }, $node;
$node->{_parent} = $self;
weaken $node->{_parent};
$self;
}
sub is_child {
my ($self, $that) = @_;
for my $child ($self->children) {
return 1 if $child->equals($that);
}
return;
}
sub is_sister {
my ($self, $that) = @_;
return if $self->is_root;
for my $sister ($self->parent->children) {
return 1 if $sister->equals($that);
}
return;
}
sub children {
my ($self, $filter) = @_;
my @children = @{$self->{_children}};
if ($filter) {
grep { $filter->($_) } @children;
} else {
@children;
}
}
sub parent {
shift->{_parent};
}
sub is_root {
shift->parent ? 0 : 1;
}
sub root {
my $node = shift;
while (1) {
return $node if $node->is_root;
$node = $node->parent;
}
}
sub depth {
my $node = shift;
my $depth = 0;
while (1) {
return $depth if $node->is_root;
$node = $node->parent;
$depth++;
}
}
use constant STOP => -1;
sub walk_down {
my ($self, $callback, $depth) = @_;
( run in 3.105 seconds using v1.01-cache-2.11-cpan-7f9471e7e0a )