【问题标题】:Reference counting problem with Perl 5.12.3?Perl 5.12.3 的引用计数问题?
【发布时间】:2011-08-09 21:11:17
【问题描述】:

看来清理垫子太早了:

sub search { 
    my ( $self, $test ) = @_;
    my $where;
    my $found   = 0;
    my $counter = 0;

    $self->descend( pre_each => sub {
        my $lvl = shift;
        my $ev_return 
            = $lvl->each_value( sub {
               $counter++;
            my ( $name, $value ) = @_;
            say "\$name=$name";
            say "\$value=$value";
            return 1 unless $found = $test->( $value );
            $where = { key => $lvl, name => $name, value => $value };
            # when any intermediate function sees QUIT_FLAG, it 
            # knows to return control to the method that called it.
            return QUIT_FLAG; 
        });
        say "\$found=$found";
        say "\$where=$where";
        return $ev_return;      
    });
    say "\$counter=$counter";
    say "\$found=$found";
    say "\$where=$where";
    return unless $found;
    return $where;
}

我得到的是:

...
$found=1
$where=HASH(...)
$counter=0
$found=0
$where=

或者,如果有人能指出我正在做的蠢事,我将不胜感激。我什至在第一个闭包和外部闭包之间创建了增量变量,但它们也被重置了。即使在最里面的闭包上设置 references,在命名的子范围内也得不到任何东西!

这里涉及的整个代码是 500 行。包含代码是不切实际的。

【问题讨论】:

  • “清理垫”是什么意思?你期望得到什么输出? descendeach_value 方法到底有什么作用?
  • @Jack Maney,当我打印出中间循环中的值时,$found1$where 是一个哈希值。当我在搜索中打印这些值时,它们都被重置为其原始值,就好像它们是本地化的包变量(它们不是)。所以我将它们设置在内部闭包中,它们保留了中间的值,但它们完全设置回search中的原始值。
  • Axeman:perl 文档多年来一直警告不要使用这种条件初始化 - 请参阅“Here be dragons”。在 perlsyn。基本上,您绕过了 my 的运行时效果,这通常不是您想要的(并且在未来的 perl 版本中可能会发生变化)。
  • 就远距离的操作而言,我猜你只是因为my ... if 没有按照你的意图做而导致的直接逻辑错误。但是如果没有一个独立的例子来尝试,就不可能说。
  • @ysth,是的,现在这很有意义,通常在语句末尾挂一个条件后缀会阻止语句的任何部分运行,并且它会使用 my .我认为失败在于strict 没有抱怨,因为——你有点没有声明变量。所以让我直截了当地说:它绕过strict 并成为一个 package 变量?

标签: perl lexical-scope


【解决方案1】:

如果你能提供一个完整的、可运行的例子,那就太好了。

暗中刺探:在外部匿名子中额外使用 $found 是否有帮助(例如 $found if 0;)?

【讨论】:

  • 我已经尝试了所有方法,包括一个由 setter 和 getter 组成的新词法范围;
  • 我必须把这个给你,因为你指出了 my with 修饰符的问题。但是人们应该看到我的帖子来了解交易的内容。谢谢。
【解决方案2】:

不要将my 与语句修饰符一起使用!

问题出在一个被调用的范围内。忘记了使用带有语句修​​饰符的my 的警告后,我编写了以下代码:

my $each   = shift if @_ == 1;
my %params = @_ unless $each;

第一次通过@_ 有一个参数。它将第一个值分配给$each。第二次通过,更多的参数它跳过my。所以当前范围内没有声明,所以它只是重用了我上次分配的 sub,并且在 %params 中没有保存任何内容,因为它引用的 $each 一个值。

很奇怪,但正如 ysth 指出的那样,perlsyn 警告不要这种行为。我想我曾经知道这一点,但多年来已经忘记了。切换到

my ( %params, $each );
if ( @_ == 1 ) { 
    $each = shift;
}
else { 
    %params = @_;
}

成功了。它不仅清理了我在使用另一种方法时遇到的问题,而且还清理了search 中的问题。

【讨论】:

    猜你喜欢
    • 2011-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-04
    • 1970-01-01
    • 2011-12-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多