Reputation: 135
for my project I need to build a tree structure. I am looking for a way to grow it at the leaves. I have simplified my failed attempt by using a listy structure:
my $root = a => (b => (c=> Nil));
my $here := $root;
while $here.value ~~ Pair {
$here := $here.value;
}
$here = d => Nil;
which does not work, because I cannot change Nil, of course. Cannot assign to an immutable value How can I make this work?
Thanks, Theo van den Heuvel
Upvotes: 5
Views: 215
Reputation: 135
On the basis of valuable input from @Elizabeth, @Håkon and @jjmerelo I have created an example tree implementation.
my @paths = <<aap-noot-mies aap-noot-hut aap-juf tuin>>;
my %root;
for @paths -> $fn {
my @path = $fn.split: '-';
add-to-tree(@path);
}
print_tree(0, %root);
sub add-to-tree(@path) {
my %tmp := %root;
for @path -> $step {
unless %tmp{$step}:exists {
my %newtmp;
%tmp{$step} = %newtmp;
}
%tmp := %tmp{$step};
}
}
sub print_tree($ind, %from) {
my $margin = ' ' x $ind;
if %from {
for %from.kv -> $k, $v {
say "$margin$k:";
print_tree($ind + 1, %$v);
}
} else {
say "$margin.";
}
}
Upvotes: 1
Reputation: 23517
You are using binding, not assignment for $here
my $root = a => (b => (c=> Nil));
my $here = $root;
while $here.value ~~ Pair {
$here = $here.value;
}
$here = d => Nil;
When you use bind, the left and the right-hand side are the same object. And once they are the same object, well, they can't change (if the bound object is immutable, that is). They're immutable:
my $bound := 3; $bound = 'þorn'; say $bound;
# OUTPUT: «Cannot assign to an immutable value»
3
above is immutable, so you can't assign to it. In the code you have provided, you could change the value by rebinding until you arrived to an immutable value, the last Pair
, which explains the message.
Just use ordinary assignment and you're good to go. If what you want is to keep the original value of $root
somewhere, just do this and use $root
to do the tree navigation
my $root = a => (b => (c=> Nil));
my $here = $root;
while $root.value ~~ Pair {
$root = $root.value;
}
$here = d => Nil;
say $here;
say $root;
$here
will still be equal to the original root, and $root
will have navigated to the last branch and leaf.
Upvotes: 3
Reputation: 40748
I think the error message you get "Cannot assign to an immutable value" is because the value is not a container. Here is an example where I make the leaf node a container:
my $root = a => (b => (my $ = (c => Nil)));
my $here := $root;
while $here.value ~~ Pair {
$here := $here.value;
}
$here = d => Nil;
Now, there is no error message.
Upvotes: 4