Perl6-Pugs

 view release on metacpan or  search on metacpan

ext/Tree/lib/Tree.pm  view on Meta::CPAN


method  get_all_siblings ($self:) returns Array {
    (!$self.is_root()) 
        || die "Insufficient Arguments : cannot get siblings to a ROOT tree";
    $self.parent().get_all_children();
}

method add_sibling ($self: Tree $sibling) returns Tree {
    (!$self.is_root()) 
        || die "Insufficient Arguments : cannot add a sibling to a ROOT tree";
    $self.parent().add_child($sibling);
}

method add_siblings ($self: *@siblings) returns Tree {
    (!$self.is_root()) 
        || die "Insufficient Arguments : cannot add siblings to a ROOT tree";
    $self.parent().add_children(@siblings);
}

method insert_siblings ($self: Int $index, *@siblings) returns Tree {
    (!$self.is_root()) 
        || die "Insufficient Arguments : cannot insert siblings to a ROOT tree";
    $self.parent().insert_children($index, @siblings);
}

# insertSibling is really the same as
# insertSiblings, you are just inserting
# and array of one tree
our &Tree::insert_sibling ::= &Tree::insert_siblings;

# I am not permitting the removal of siblings 
# as I think in general it is a bad idea

## ----------------------------------------------------------------------------
## traversal

method traverse ($self: Code $func, Str $traversal_order?) returns Void {
    if !$traversal_order.defined || $traversal_order.lc() eq 'pre_order' {
        $self.pre_order_traverse($func)
    }
    else {
        $self.post_order_traverse($func)
    }
}

method pre_order_traverse ($self: Code $func) returns Void {
    for @!children -> $child is rw {
        $func($child);
        $child.traverse($func);
    }
}

method post_order_traverse ($self: Code $func) returns Void {
    for @!children -> $child is rw {
        $child.traverse($func);
        $func($child);
    }
}

method traverse_iter($self: Str $traversal_order?) returns Code {
    return coro {
        $self.traverse(sub { yield $^node }, $traversal_order);
    };
}

## ----------------------------------------------------------------------------
## utility methods

# NOTE:
# Occasionally one wants to have the 
# depth available for various reasons
# of convience. Sometimes that depth 
# field is not always correct.
# If you create your tree in a top-down
# manner, this is usually not an issue
# since each time you either add a child
# or create a tree you are doing it with 
# a single tree and not a hierarchy.
# If however you are creating your tree
# bottom-up, then you might find that 
# when adding hierarchies of trees, your
# depth fields are all out of whack.
# This is where this method comes into play
# it will recurse down the tree and fix the
# depth fields appropriately.
# This method is called automatically when 
# a subtree is added to a child array
method fix_depth ($self:) returns Void {
    # make sure the tree's depth 
    # is up to date all the way down
    $self.traverse(-> $t {
        $t!set_depth($t.parent().depth() + 1);
    });
}

# NOTE:
# This method is used to fix any height 
# discrepencies which might arise when 
# you remove a sub-tree
method fix_height ($self:) returns Void {
    # we must find the tallest sub-tree
    # and use that to define the height
    my $max_height = 0;
    unless ($self.is_leaf()) {
        for @!children -> $child is rw {
            my $child_height = $child.height();
            $max_height = $child_height if $max_height < $child_height;
        }
    }
    # if there is no change, then we 
    # need not bubble up through the
    # parents
    return if $.height == ($max_height + 1);
    # otherwise ...
    $.height = $max_height + 1;
    # now we need to bubble up through the parents 
    # in order to rectify any issues with height
    $self.parent().fix_height() unless $self.is_root();
}

method fix_width ($self:) {



( run in 5.385 seconds using v1.01-cache-2.11-cpan-56fb94df46f )