1

ループ内で値をキャッシュするように perl コンパイラに指示/強制する方法はありますか?

もちろん、ループの外で値を作成することもできますが、コードの複雑さが増すにつれて、ループ内で値を作成した方が読みやすいと思いますが、値は変更されません。

例えば:

my $key = shift;
my @input = @_;
my %output;
foreach(@input) {
    my $output_tmp = specialOperation($_);
    ...
    my $key_tmp = constantOperation($key);
    my $specialKey = specialOperation2($_,$key_tmp);
    ...
    $output{$specialKey} = $tmp;
}

$keyTmpすべての反復で同じ値を持ち、コンパイラーにキャッシュさせたい

正規表現では、o-flag
これを達成するために、キーワードなど、似たようなものがありますか?を使用できます。

4

2 に答える 2

4

次のようにコードを変更しても、複雑さが増すことはありません。

my $key_tmp = constantOperation($key);
my %output
foreach ( @input ) {
    my $output_tmp = special_operation($_);
    my $specialKey = specialOperation2($_,$key_tmp);
    $output{$specialKey} = $tmp;
}

しかし、なぜそれをしたくないのかについて、非公開の合理的な議論があることを少しの間受け入れると、別の可能性 (constantOperation が純粋な関数である場合) は、Memoize を使用することです。

use Memoize;
memoize 'constantOperation';

my $key = shift;
my @input = @_;
my %output;
foreach( @input ) {
    my $output_tmp = special_operation;
    my $key_tmp = constantOperation($key);
    my $specialKey = specialOperation2($_,$key_tmp);
    $output{$specialKey} = $tmp;
}

後者は関数呼び出しの繰り返しを回避しませんが、constantOperation と呼ばれる関数内でキャッシュを発生させるため、以前に使用されたパラメーターを使用した後続の呼び出しでは、キャッシュされた結果が提供されます。

最初の例に戻ると、「my」宣言をループの外に移動し、ループ内で次のようなものを使用できます $key_tmp //= constantOperation($key);。これがどのように見えるかを次に示します。

my $key = shift;
my @input = @_;
my %output;
my $key_tmp;
foreach( @input ) {
    my $output_tmp = special_operation;
    $key_tmp //= constantOperation($key);
    my $specialKey = specialOperation2($_,$key_tmp);
    $output{$specialKey} = $tmp;
}

これが Perl であるため、それを行う方法は常に 1 つ以上あります。「状態」機能を有効にして、に変更my $key_tmpstate $key_tmpます。これがどのように見えるかを次に示します。

use feature 'state';
my $key = shift;
my @input = @_;
my %output;
foreach( @input ) {
    my $output_tmp = special_operation;
    state $key_tmp = constantOperation($key);
    my $specialKey = specialOperation2($_,$key_tmp);
    $output{$specialKey} = $tmp;
}
于 2012-08-13T09:41:24.427 に答える
0

ループの外側で宣言$key_tmpし、ループ内で再計算する前に既に割り当てられているかどうかを確認します。

my ($key, @input) = @_;
my %output;
my $key_tmp;

foreach(@input) {
    my $output_tmp = specialOperation($_);
    ...
    $key_tmp = constantOperation($key) unless $key_tmp;
    my $specialKey = specialOperation2($_,$key_tmp);
    ...
    $output{$specialKey} = $tmp;
}
于 2012-08-13T10:26:25.853 に答える