AUTOLOAD
またはその他のサブルーチン ディスパッチ手法を使用する Perl モジュールを開発しているときに、次のパターンに何度か遭遇しました。
sub AUTOLOAD {
my $self = $_[0];
my $code = $self->figure_out_code_ref( $AUTOLOAD );
goto &$code;
}
これは正常に機能caller
し、正しいスコープが表示されます。
今私がしたいのは、の実行中にローカルで$_
等しいに設定することです。これは次のようになります。$self
&$code
sub AUTOLOAD {
my $self = $_[0];
my $code = $self->figure_out_code_ref( $AUTOLOAD );
local *_ = \$self;
# and now the question is how to call &$code
# goto &$code; # wont work since local scope changes will
# be unrolled before the goto
# &$code; # will preserve the local, but caller will report an
# additional stack frame
}
ラッピングを含むソリューションは、caller
パフォーマンスと依存関係の問題により受け入れられません。したがって、それは2番目のオプションを除外しているようです.
最初に戻ると、 の新しい値が$_
の範囲外に出ないようにする唯一の方法goto
は、変更をローカライズしない (実行可能なオプションではない) か、または のようなものを実装することuplevel_local
ですgoto_with_local
。
PadWalker
、Sub::Uplevel
、Scope::Upper
、およびその他を含むあらゆる種類の順列を試してみましたが、適切なタイミングでクリーンアップし、ラップしないB::Hooks::EndOfScope
堅牢なソリューションを思い付くことができませんでした。$_
caller
この場合に機能するパターンを見つけた人はいますか?
(SO の質問:別のスタック フレームで Perl 変数をローカライズするにはどうすればよいですか?は関連していますが、保持することcaller
は要件ではなく、最終的には別のアプローチを使用するという答えがあったため、この場合、その解決策は役に立ちません)