变量不受保护

The variable is not protected

我有这个来源 首先 start.pl

use strict;
use warnings;

use hh;

print "Starting...\n";

my $abc={
    VAL=>['alfa','beta'],
    STUDENTS=>{
        stud1=>{VAL=>['delta','gama']},
        stud2=>{VAL=>['omega','upsilon']},
            }
    };
my $object=hh->new(catalog=>$abc);

和包裹

package hh;
use strict;
use warnings;

sub new {
    my $class=shift;
    my $self={@_};
    bless ($self,$class) ; 
    $self->_initialize("",['BEGIN']);
    return $self ; 
}




sub _initialize {
    my $self=shift;
    my $tab=shift;
    my $carry=shift;
    $tab=$tab."\t|";
    
    if (defined $self->{VAL}){print "$tab Have  val=",join(" ",@{$self->{VAL}}),"\n";push(@{$carry},@{$self->{VAL}})}
    foreach my $k (sort {lc $a cmp lc $b} keys %{$self}){
        print $tab,"carry=",$#{$carry}+1," "," ",$k,"\n";
        if (ref($self->{$k}) eq 'HASH'){print "$tab Running initialize pentru $k\n";_initialize($self->{$k},$tab,$carry)}
    }

return $self;
}

1;

输出是这样的

Starting...
    |carry=1  catalog
    | Running initialize pentru catalog
    |   | Have  val=alfa beta
    |   |carry=3  STUDENTS
    |   | Running initialize pentru STUDENTS
    |   |   |carry=3  stud1
    |   |   | Running initialize pentru stud1
    |   |   |   | Have  val=delta gama
    |   |   |   |carry=5  VAL
    |   |   |carry=5  stud2
    |   |   | Running initialize pentru stud2
    |   |   |   | Have  val=omega upsilon
    |   |   |   |carry=7  VAL
    |   |carry=7  VAL

我想以某种方式将树顶部和遍历元素之间的 VAL 数组收集到一个数组中。第二层的最后一个 VAL 有 7 个元素。我只想有 2 个元素(alfa 和 beta)

这是预期的输出

Starting...
    |carry=1  catalog
    | Running initialize pentru catalog
    |   | Have  val=alfa beta
    |   |carry=3  STUDENTS
    |   | Running initialize pentru STUDENTS
    |   |   |carry=3  stud1
    |   |   | Running initialize pentru stud1
    |   |   |   | Have  val=delta gama
    |   |   |   |carry=5  VAL   carry=5                  (OK)
    |   |   |carry=5  stud2
    |   |   | Running initialize pentru stud2
    |   |   |   | Have  val=omega upsilon
    |   |   |   |carry=7  VAL      carry=5   (not ok this need only his values catalog alfa beta omega epsilon)
    |   |carry=7  VAL not ok (carry 3  only catalog alfa beta)

...

如果只想累加当前分支中的值,则必须传递进位数组的副本。 [@$carry] 取消引用 arrayref $carry 并从元素创建一个新的 arrayref。我在函数末尾保留了调试打印的原始参考。更自然的方式是写 $carry = [@$carry].

use strict;
use warnings;

package hh;
use Data::Dumper;
sub new {
    my $class=shift;
    my $self={@_};
    bless ($self,$class) ; 
    $self->_initialize("",['BEGIN']);
    return $self ; 
}




sub _initialize {
    my $self=shift;
    my $tab=shift;
    my $carry=shift;
    $tab=$tab."\t|";
    print "$tab _initialize() called with carry "," [",join(', ',@$carry),"]\n";
    my $new_carry =  [@$carry];
    if (defined $self->{VAL}){
        print "$tab Have found val=",join(" ",@{$self->{VAL}}),"\n";
        print "$tab pushing ",join(" ",@{$self->{VAL}}),"\n";
        push(@{$new_carry},@{$self->{VAL}})
    }
    print $tab," carry=",$#{$new_carry}+1," [",join(', ',@$new_carry),"]\n";

    foreach my $k (sort {lc $a cmp lc $b} keys %{$self}){
        if (ref($self->{$k}) eq 'HASH'){print "$tab Running initialize pentru $k\n";_initialize($self->{$k},$tab, $new_carry)}
    }
    print "$tab returning to previous level. carry was "," [",join(', ',@$carry),"]\n";
    return $self;
}

package main;
print "Starting...\n";

my $abc={
    VAL=>['alfa','beta'],
    STUDENTS=>{
        stud1=>{VAL=>['delta','gama']},
        stud2=>{VAL=>['omega','upsilon']},
            }
    };
my $object=hh->new(catalog=>$abc);

这会打印:

Starting...
    | _initialized called with carry  [BEGIN]
    | carry=1 [BEGIN]
    | Running initialize pentru catalog
    |   | _initialized called with carry  [BEGIN]
    |   | Have found val=alfa beta
    |   | pushing alfa beta
    |   | carry=3 [BEGIN, alfa, beta]
    |   | Running initialize pentru STUDENTS
    |   |   | _initialized called with carry  [BEGIN, alfa, beta]
    |   |   | carry=3 [BEGIN, alfa, beta]
    |   |   | Running initialize pentru stud1
    |   |   |   | _initialized called with carry  [BEGIN, alfa, beta]
    |   |   |   | Have found val=delta gama
    |   |   |   | pushing delta gama
    |   |   |   | carry=5 [BEGIN, alfa, beta, delta, gama]
    |   |   |   | returning to previous level. carry was  [BEGIN, alfa, beta]
    |   |   | Running initialize pentru stud2
    |   |   |   | _initialized called with carry  [BEGIN, alfa, beta]
    |   |   |   | Have found val=omega upsilon
    |   |   |   | pushing omega upsilon
    |   |   |   | carry=5 [BEGIN, alfa, beta, omega, upsilon]
    |   |   |   | returning to previous level. carry was  [BEGIN, alfa, beta]
    |   |   | returning to previous level. carry was  [BEGIN, alfa, beta]
    |   | returning to previous level. carry was  [BEGIN]
    | returning to previous level. carry was  [BEGIN]