“变量 $foo 不会保持共享";调用子程序时 Perl 中的警告/错误 [英] "Variable $foo will not stay shared" Warning/Error in Perl While Calling Subroutine

查看:52
本文介绍了“变量 $foo 不会保持共享";调用子程序时 Perl 中的警告/错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Update3:如果你喜欢这篇文章,请不要给我点赞,而是点赞下面 DVK 的天才回答.

Update3: If you like this posting please don't upvote me but upvote the genius answer by DVK below.

我有以下子程序:

 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;
}

但为什么它会给出这个信息:

But why it gives this message:

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.

有害吗?错误?如何修复我的代码以消除该消息?

Is it harmful? Error? How can fix my code so that it get rid of that message?

Update1:​​我使用实际错误消息更新了按原样运行的代码

Update1: I update the code that runs as is with the actuall error message

Update2: 我尝试按照 DVK 的建议使用 sub 进行修改.它奏效了!

Update2: I tried to modify using sub as DVK suggested. And it WORKED!

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;
}

推荐答案

根据 perldoc 的 perldiag对于该错误,您的问题是内部子程序引用了外部子程序中定义的词法变量(%marked).

As per perldoc's perldiag for that error, your problem is that the inner sub is referencing a lexical variable (%marked) defined in the outer sub.

修复在第三段(使用匿名子):

The fix is in the third paragraph (use anonymous sub):

(警告;关闭)一个内部(嵌套)命名子程序正在引用一个词法在外部命名的变量中定义子程序.

(Warning; closure) An inner (nested) named subroutine is referencing a lexical variable defined in an outer named subroutine.

调用内部子程序时,它会看到外部的价值子程序的变量和以前一样在第一次调用外层子程序;在这种情况下,在第一次调用外部子程序完成了,内部和外部子程序将不再共享一个变量的通用值.在换句话说,变量不会不再分享.

When the inner subroutine is called, it will see the value of the outer subroutine's variable as it was before and during the first call to the outer subroutine; in this case, after the first call to the outer subroutine is complete, the inner and outer subroutines will no longer share a common value for the variable. In other words, the variable will no longer be shared.

这个问题通常可以通过以下方式解决使内部子程序匿名,使用 sub {} 语法.当内引用的匿名订阅外部子程序中的变量是创建后,它们会自动反弹到当前值变量.

This problem can usually be solved by making the inner subroutine anonymous, using the sub {} syntax. When inner anonymous subs that reference variables in outer subroutines are created, they are automatically rebound to the current values of such variables.

使用匿名子修复代码:

# ....
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];
}
# ....

这篇关于“变量 $foo 不会保持共享";调用子程序时 Perl 中的警告/错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆