I have following script that need to understand
&main('key_1');
sub main {
@{$tmp{'key_1'}} = ("A", "B");
@{$tmp{'A'}} = ("C");
&test_recurse(\%tmp, 'key_1');
}
sub test_recurse {
my ($hash, $cell) = @_;
foreach my $cur_subcell (@{$hash->{$cell}}){
&test_recurse($hash, $cur_subcell);
}
print "X($cell)\n";
}
The output:
X(C)
X(A)
X(B)
X(key_1)
I want to understand why the key_1
is printing at the last? I am expecting the key_1
might not be printed at all.
CodePudding user response:
I am expecting the
key_1
might not be printed at all
The function test_recurse
ends with print "X($cell)\n"
. This means that it ends by printing its second argument. Since you initially call it with key_1
as argument, it prints X(key_1)
.
To understand a bit better how the function test_recurse
works, I suggest to add some prints as follows:
sub test_recurse {
my ($hash, $cell, $offset) = @_;
print "${offset}test_recurse($cell)\n";
foreach my $cur_subcell (@{$hash->{$cell}}){
&test_recurse($hash, $cur_subcell, $offset . " ");
}
print "${offset}X($cell)\n";
}
Thanks to the addition of $offset
, each time you make a recursive call, the prints within this recursive call are indented further to the right. Calling this modified function with test_recurse(\%tmp, 'key_1', "")
, you'll get this output:
test_recurse(key_1)
test_recurse(A)
test_recurse(C)
X(C)
X(A)
test_recurse(B)
X(B)
X(key_1)
So, what happens is:
You call
test_recurse
withkey_1
. This printstest_recurse(key_1)
. In the foreach loop, it will make two successive calls totest_recurse
:The first one with
A
as argument. This will printtest_recurse(A)
. In the foreach loop, it will make a call totest_recurse
withC
as argument. This will printtest_recurse(C)
. Since$tmp{C}
does not exist, this call does not enter in theforeach
loop, and directly proceed to the final print and printsX(C)
. We then go back to the caller (test_recurse
withA
as argument).
Now that the
foreach
loop is done, this function moves on to the lastprint
and printsX(A)
. We then go back to the caller (test_recurse
withkey_1
as argument).The second recursive call is to
test_recurse
withB
as argument. This will printtest_recurse(B)
. Since$tmp{B}
does not exist, we do not enter theforeach
loop and move on to the final print, which printsX(B)
. We then return to the caller (test_recurse
withkey_1
as argument).
The
foreach
loop is now over and we move on to the finalprint
, which printsX(key_1)
.
Some tips:
Always add
use strict
anduse warnings
at the beginning of your scripts.@{$tmp{'key_1'}} = ("A", "B");
would be clearer as$tmp{'key_1'} = [ 'A', 'B' ]
.The whole initialization of
%tmp
could actually be done with:my %tmp = ( key_1 => [ 'A', 'B' ], A => [ 'C' ] );
You call
&main('key_1');
withkey_1
as argument, butmain
does not expect any argument.To call a function, you don't need
&
: dotest_recurse(\%tmp, 'key_1');
instead of&test_recurse(\%tmp, 'key_1');
.
CodePudding user response:
In a comment, you say:
I am just thinking that as if the variable
$cell
has been replace by C, A, B why thekey_1
is coming back at the end.
And I think that's probably a good indication of where the confusion lies.
Your test_recurse()
subroutine starts with this line:
my ($hash, $cell) = @_;
That defines two new variables called $hash
and $cell
and then populates them from @_
. Because these variables are declared using my
, they are lexical variables. That means they are only visible within the block of code where they are declared.
Later on in test_recurse()
you call the same subroutine again. And, once again, that subroutine starts with the same declaration statement and creates another two variables called $hash
and $cell
. These two new variables are completely separate from the original two variables. The original variables still exist and still contain their original values - but you can't currently access them because they are declared in a different call to the subroutine.
So when your various calls to the subroutine end, you rewind back to the original call - and that still has the original two variables which still hold their original values.