我有以下腳本需要理解
&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";
}
輸出:
X(C)
X(A)
X(B)
X(key_1)
我想了解為什么key_1最后列印?我期待key_1可能根本不會列印。
uj5u.com熱心網友回復:
我期待
key_1可能根本不會列印
函式test_recurse以print "X($cell)\n". 這意味著它以列印第二個引數結束。由于您最初使用key_1as 引數呼叫它,因此它列印X(key_1).
為了更好地理解函式的test_recurse作業原理,我建議添加一些列印如下:
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";
}
由于添加了$offset,每次進行遞回呼叫時,此遞回呼叫中的列印都會進一步向右縮進。用 呼叫這個修改過的函式test_recurse(\%tmp, 'key_1', ""),你會得到這個輸出:
test_recurse(key_1)
test_recurse(A)
test_recurse(C)
X(C)
X(A)
test_recurse(B)
X(B)
X(key_1)
所以,會發生什么:
你叫
test_recurse用key_1。這列印test_recurse(key_1). 在 foreach 回圈中,它將連續兩次呼叫test_recurse:第一個帶有
Aas 引數。這將列印test_recurse(A). 在 foreach 回圈中,它將呼叫test_recurse與C作為引數。這將列印test_recurse(C). 由于$tmp{C}不存在,本次呼叫不進入foreach回圈,直接進行最后的print和printsX(C)。然后,我們回去給呼叫者(test_recurse以A作為引數)。
現在
foreach回圈已完成,此函式繼續執行最后一個print并列印X(A). 然后,我們回去給呼叫者(test_recurse以key_1作為引數)。第二個遞回呼叫是
test_recursewithB作為引數。這將列印test_recurse(B). 由于$tmp{B}不存在,我們不進入foreach回圈并繼續進行最終列印,列印X(B). 然后,我們回傳給呼叫者(test_recurse以key_1作為引數)。
該
foreach回圈已經過去,我們進入到最后的print,列印X(key_1)。
一些技巧:
始終在腳本的開頭添加
use strict和use warnings。@{$tmp{'key_1'}} = ("A", "B");會更清楚$tmp{'key_1'} = [ 'A', 'B' ]。的整個初始化
%tmp實際上可以通過以下方式完成:my %tmp = ( key_1 => [ 'A', 'B' ], A => [ 'C' ] );您
&main('key_1');使用key_1as 引數呼叫,但main不期望任何引數。要呼叫函式,您不需要
&: dotest_recurse(\%tmp, 'key_1');而不是&test_recurse(\%tmp, 'key_1');。
uj5u.com熱心網友回復:
在評論中,你說:
我只是在想,好像變數
$cell已被 C、A、B 替換,為什么最后key_1又回來了。
我認為這可能是混淆所在的一個很好的跡象。
您的test_recurse()子程式以這一行開始:
my ($hash, $cell) = @_;
這定義了兩個名為$hash和 的新變數$cell,然后從@_. 因為這些變數是使用 宣告的my,所以它們是詞法變數。這意味著它們僅在宣告它們的代碼塊中可見。
稍后test_recurse()您再次呼叫相同的子程式。并且,該子例程再次以相同的宣告陳述句開始,并創建另外兩個名為$hashand 的變數$cell。這兩個新變數與原來的兩個變數完全分開。原始變數仍然存在并且仍然包含它們的原始值——但是您目前無法訪問它們,因為它們是在對子例程的不同呼叫中宣告的。
因此,當您對子例程的各種呼叫結束時,您會退回到原始呼叫 - 并且仍然具有仍然保留其原始值的原始兩個變數。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/325977.html
