nev*_*int 20 unix perl scope local-functions
Update3: 如果你喜欢这个帖子,请不要赞成我,但请通过下面的DVK赞助天才答案.
我有以下子程序:
use warnings;
#Input
my @pairs = (
"fred bill",
"hello bye",
"hello fred",
"foo bar",
"fred foo");
#calling the subroutine
my @ccomp = connected_component(@pairs);
use Data::Dumper;
print Dumper \@ccomp;
sub connected_component {
my @arr = @_;
my %links;
foreach my $arrm ( @arr ) {
my ($x,$y) = split(/\s+/,$arrm);;
$links{$x}{$y} = $links{$y}{$x} = 1;
}
my %marked; # nodes we have already visited
my @stack;
my @all_ccomp;
for my $node (sort keys %links) {
next if exists $marked{$node};
@stack = ();
connected($node);
print "@stack\n";
push @all_ccomp, [@stack];
}
sub connected {
no warnings 'recursion';
my $node = shift;
return if exists $marked{$node}; # Line 43
$marked{$node} = 1;
push @stack, $node; # Line 45
my $children = $links{$node}; # Line 46
connected($_) for keys %$children;
}
return @all_ccomp;
}
Run Code Online (Sandbox Code Playgroud)
但为什么它会给出这样的信息:
Variable "%marked" will not stay shared at mycode.pl line 43.
Variable "@stack" will not stay shared at mycode.pl line 45.
Variable "%links" will not stay shared at mycode.pl line 46.
Run Code Online (Sandbox Code Playgroud)
有害吗?错误?如何修复我的代码,以便它摆脱那条消息?
Update1:我使用actuall错误消息更新运行的代码
Update2:我尝试使用sub修改为DVK建议.它工作了!
use warnings;
#Input
my @pairs = (
"fred bill",
"hello bye",
"hello fred",
"foo bar",
"fred foo");
#calling the subroutine
my @ccomp = connected_component(@pairs);
use Data::Dumper;
print Dumper \@ccomp;
sub connected_component {
my @arr = @_;
my %links;
foreach my $arrm ( @arr ) {
my ($x,$y) = split(/\s+/,$arrm);;
$links{$x}{$y} = $links{$y}{$x} = 1;
}
my %marked; # nodes we have already visited
my @stack;
my @all_ccomp;
my $connected_sub;
$connected_sub = sub {
no warnings 'recursion';
my $node = shift;
return if exists $marked{$node};
$marked{$node} = 1;
push @stack, $node;
my $children = $links{$node};
&$connected_sub($_) for keys %$children;
};
for my $node (sort keys %links) { # Line 43
next if exists $marked{$node};
@stack = ();
&$connected_sub($node);
#print "@stack\n";
push @all_ccomp, [@stack]; # Line 49
}
return @all_ccomp;
}
Run Code Online (Sandbox Code Playgroud)
DVK*_*DVK 53
根据perldoc对该错误的perldiag,你的问题是内部子引用外部子中定义的词法变量(%标记).
修复程序在第三段(使用匿名子):
(警告;闭包)内部(嵌套)命名子例程引用外部命名子例程中定义的词法变量.
当调用内部子程序时,它将看到外部子程序变量的值,就像它在第一次调用外部子程序之前和期间一样; 在这种情况下,在第一次调用外部子程序完成后,内部子程序和外部子程序将不再共享该变量的公共值.换句话说,该变量将不再共享.
通常可以通过使用sub {}语法使内部子例程匿名来解决此问题.当创建引用外部子例程中的变量的内部匿名子时,它们会自动回弹到这些变量的当前值.
使用匿名子修复代码:
# ....
my $connected_sub;
$connected_sub = sub {
no warnings 'recursion';
my $node = shift;
return if exists $marked{$node}; # Line 280
$marked{$node} = 1;
push @stack, $node; # Line 282
my $children = $links{$node}; # Line 283
&$connected_sub($_) for keys %$children;
};
for my $node (sort keys %links) {
next if exists $marked{$node};
@stack = ();
&$connected_sub($node);
#print "@stack\n";
push @all_ccomp, [@stack];
}
# ....
Run Code Online (Sandbox Code Playgroud)
另一个(可能更简单)出路是将变量声明为"我们的"而不是"我的"
所以,
our %marked;
Run Code Online (Sandbox Code Playgroud)
代替
my %marked;
Run Code Online (Sandbox Code Playgroud)
等等