24

いくつかのコードのさまざまな場所に次のことを効果的に書き出す自動生成コードがあります。

no warnings 'uninitialized';
local %ENV = %ENV;
local $/   = $/;
local @INC = @INC;
local %INC = %INC;
local $_   = $_;
local $|   = $|;
local %SIG = %SIG;
use warnings 'uninitialized';

コードを自動生成するとき、コードが「美しい」ものである必要はないと主張する人もいますが、私はそれをサブルーチンに引き出したいと考えています。ただし、それはそのサブルーチンでそれらの変数をローカライズします。呼び出し元のスタック フレームでこれらの変数をローカライズする方法はありますか?

更新: 同様に、より高いスタック フレームで eval を実行できると便利です。Pythonにはすでにこれがあると思います。Perlもそうなればいいのに。

4

6 に答える 6

30

おそらく、これらのローカルを使用するコードをクロージャーとして生成するように調整できますか?その後、あなたはすることができます

sub run_with_env {
    my ($sub, @args) = @_;
    no warnings 'uninitialized';
    local %ENV = %ENV;
    local $/   = $/;
    local @INC = @INC;
    local %INC = %INC;
    local $_   = $_;
    local $|   = $|;
    local %SIG = %SIG;
    use warnings 'uninitialized';  
    $sub->(@args);
}

run_with_env(sub {
    # do stuff here
});

run_with_env(sub {
    # do different stuff here
});
于 2008-10-14T13:53:25.023 に答える
6

QuantumPete が反対票を投じられている理由がわかりませんが、彼はこれについて正しいようです。local呼び出しブロックで変数を初期化するように指示することはできません。その機能は特殊であり、それが行う初期化/ティアダウンは、それが実行されたブロックでのみ機能します。

Sub::UplevelDevel:: RunBlockなどの実験的なモジュールがいくつかあり、サブルーチンを「だます」ことを試みcaller()たり、より高いスタック フレームへの値の「ロング ジャンプ リターン」を (それぞれ) 実行したりできますが、どちらも実行しません。local変数の処理方法に影響を与えるものすべて(試しました。:)

したがって、今のところ、必要なスコープでローカル宣言を使用する必要があるように見えます。

于 2008-10-14T12:28:40.437 に答える
3

perldoc perlguts さんのコメント:

   The "Alias" module implements localization of the basic types within
   the caller's scope.  People who are interested in how to localize
   things in the containing scope should take a look there too.

ふぅ。私は Alias.pm を十分に調べて、これがどれほど簡単であるかを確認していません。

于 2008-10-15T01:53:47.987 に答える
3

私はPerlにあまり詳しくないので、実際に可能であれば許してください。ただし、通常、スタック フレームにローカルな変数は、そのスタック フレーム内でのみ使用できます。上位または下位のいずれからもそれらにアクセスすることはできません (ハッキーなポインター演算を行う場合を除きますが、それが成功することが保証されているわけではありません)。残念ながら、変数宣言の大きなブロックは、あなたが一緒に暮らす必要があるものです。

クォンタムピート

于 2008-10-14T10:05:35.310 に答える
1

TCL ではuplevelを使用できます。Perlについては、わかりません。

于 2008-10-14T11:35:21.137 に答える
0

PerlにはSub::Uplevelがあります

于 2008-10-17T22:08:19.577 に答える