Theo van den Heuvel
Theo van den Heuvel

Reputation: 135

how to create a data structure like a tree

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

Answers (3)

Theo van den Heuvel
Theo van den Heuvel

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

jjmerelo
jjmerelo

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

H&#229;kon H&#230;gland
H&#229;kon H&#230;gland

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

Related Questions