sub visit_preorder(&$) {
my ($visitor, $node) = @_;
my ($val, $l, $r) = @$node;
$visitor->() for $val;
&visit_preorder($visitor, $l) if defined $l;
&visit_preorder($visitor, $r) if defined $r;
}
####
sub visit_preorder {
my ($node) = @_;
my ($val, $l, $r) = @$node;
return (
sub { return \$val; },
sub { return visit_preorder($l) if defined $l; return; },
sub { return visit_preorder($r) if defined $r; return; },
);
}
##
##
sub visit_preorder {
my ($node) = @_;
my ($val, $l, $r) = @$node;
return (
\$val,
defined($l) ? sub { return visit_preorder($l); } : (),
defined($r) ? sub { return visit_preorder($r); } : (),
);
}
##
##
sub make_iter {
my $f = shift @_;
my @todo = $f->(@_);
return sub {
while (@todo) {
my $todo = shift @todo;
if (ref($todo) eq 'CODE') {
unshift @todo, $todo->();
} elsif (ref($todo) eq 'ARRAY') {
return @$todo;
} else {
return $$todo;
}
}
return;
};
}
##
##
{
# a
# / \
# b e
# / \ \
# c d f
my $tree = [
'a',
[
'b',
[
'c',
undef,
undef,
],
[
'd',
undef,
undef,
],
],
[
'e',
undef,
[
'f',
undef,
undef,
],
],
];
my $iter = make_iter(\&visit_preorder, $tree);
while (my ($name) = $iter->()) {
print($name);
}
print("\n");
}