开发者

Reference counting problem with Perl 5.12.3?

It seems that it's cleaning up the pad too early:

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

And what I get is:

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

Or, if anybody can point to something bone-headed I'm doing, I'd really appreciate it. I even created incremental variables between the first and outer closure, but they got reset too. Even setting references on the innermost closure, gets me nothing in the named sub scope!

The entire code concerned here is 500 lines. It is impractical to include the code.


It would be really good if you could provide a complete, runnable example.

Stab in the dark: does it help to have an extraneous use of $found in the outer anonymous sub (e.g. $found if 0;)?


Do not use my with statement modifiers!

The problem turned out to be in a called scope. Having forgotten the warning against using my with a statement modifier, I had coded the following:

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

The first time it went through @_ had one argument. It assigned the first value to $each. The second time through, with more arguments it skipped the my. So there was no declaration in the current scope, so it simply reused the sub that I had assigned the last time, and saved nothing in %params because the $each it referred to had a value.

Weird, but as ysth pointed out perlsyn warns against this behavior. I think I used to know this, but have forgotten it over the years. Switching it to

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

did the trick. It not only cleaned up the problems I was having with another method, but it cleaned up problems in search.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜