1

パッドのクリーンアップが早すぎるようです:

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=

または、誰かが私がやっていることを指し示すことができれば、本当に感謝します. 最初のクロージャーと外側のクロージャーの間にインクリメンタル変数を作成しましたが、それらもリセットされました。最も内側のクロージャーに参照を設定しても、名前付きサブスコープには何もありません!

ここで関係するコード全体は 500 行です。コードを含めることは実際的ではありません。

4

2 に答える 2

2

完全で実行可能な例を提供できれば、本当に良いでしょう。

暗闇の中で突き刺す: 外側の匿名サブ (例: $found if 0;) で $found を無関係に使用することは役に立ちますか?

于 2011-08-10T02:51:02.943 に答える
1

myステートメント修飾子と一緒に使用しないでください。

問題は呼び出されたスコープにあることが判明しました。ステートメント修飾子の使用に対する警告を忘れてmyいたので、次のようにコーディングしました。

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

それが最初に通過し@_たとき、1つの引数がありました。に最初の値を割り当てました$each。2 回目は、より多くの引数を使用my. したがって、現在のスコープには宣言がなかったので、前回割り当てたサブルーチンを単純に再利用し、参照先に値があっ%paramsたため何も保存しませんでした。$each

奇妙ですが、ysth が指摘したように、perlsyn はこの動作に対して警告します。昔は知っていたと思いますが、何年も経つと忘れてしまいます。に切り替える

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

トリックをしました。別の方法で抱えていた問題を解決しただけでなく、 の問題も解決しましたsearch

于 2011-08-10T15:26:12.487 に答える