私は何か奇妙なことに気づき始めましたScope::Guard
。
- サブの最後のステートメントとして変数の定義を解除する
$guard
と、ガードのサブが予想よりも遅く呼び出されます。 - 定義を解除しない場合、または後で何か(何か)を実行し
undef $guard
た場合、ドキュメントに記載されているように、参照がスコープ外になると呼び出されます。なんでだろうか。
コードもここにあります
my $sClass = 'SGuard';
# Uncomment to use Scope::Guard instead:
# use Scope::Guard; $sClass = 'Scope::Guard';
package SGuard;
sub new {
my ($class, $sub) = @_;
return bless { sub => $sub }, $class;
}
sub DESTROY {
my ($self) = @_;
$self->{sub}->();
}
package main;
sub mySub {
my $mySubGuard = $sClass->new(sub {
print "shouldDestroyFirst\n"
});
# Do something - any no-op will do.
undef;
# Comment out this line and it works
undef $mySubGuard;
# Or uncomment the next undef line and it works. Any statement(s) or
# no-ops will do but we test the return value of mySub to make sure it
# doesn't return a reference, so undef...
# undef;
}
{
my $scopeGuard = $sClass->new(sub {
print "shouldDestroyLast\n"
});
# Check that mySub returns undef to ensure the reference *did* go out
# of scope
printf "mySub returned a %sdefined value\n", defined mySub() ? "" : "un";
}
print "done\n";
コードでは、例をできるだけ単純にするために、自分の貧乏人Scope::Guard
(上記)を作成しました。
また、少なくとも私には予想外のまったく同じ結果をSGuard
使用して取得することもできます。Scope::Guard
$mySubGuard
内部mySub()
を最初に破棄$scopeGuard
し、呼び出し元のスコープ内をmySub()
最後に破棄することを期待しています。そして、次のような出力を取得します。
shouldDestroyFirst
mySub returned a undefined value
shouldDestroyLast
done
undef $mySubGuard
mySubでlineを使用すると、上記の出力が得られます。undef $mySubGuard
mySubで行を使用しない場合、以下の出力が得られます。
mySub returned a undefined value
shouldDestroyLast
shouldDestroyFirst
done
$mySubGuard
したがって、外部スコープにローカルな変数が破棄された後、 frommySub()
が破棄されたように見えます。
とにかくスコープから外れそうな変数の定義を解除したからといって、動作が異なるのはなぜですか?そして、なぜ後で何かが行われるかどうかが重要なのでしょうか?