2

発信者に戻るのではなく、発信者から戻る方法はありますか? 例えば

sub foo {
    bar();
    # this never gets executed
}

sub bar {
    return_from_caller(5);
}

# This prints 5
print foo();

(理論的根拠: 関数内から関数をメモ化する関数 memoize_self を作成しています。次のように動作するようにしたいと思います。

sub complex_function {
    my ($x, $y) = @_;
    memoize_self({key => $y, expires_in => '5min'));
    # compute $result
    return $result;
}

memoize_self はキャッシュをチェックし、ヒットした場合は呼び出し元からキャッシュされた値を返します。それ以外の場合は、(明らかな無限ループを回避するために動的スコープの var を使用して) 関数を再呼び出しし、戻り値をキャッシュに格納してから再度返します。

呼び出し元から戻る機能がなければ、おそらく $_ を使用して次のように記述します。

return $_ if memoize_self({key => $y, expires_in => '5min'));

しかし、これは余分なノイズであり、コンテキストも考慮されていません。)

編集:Memoizeを合理的に提案した人々へ-はい、私はこのモジュールをよく知っていると言うべきでした。私はCHIに基づいた、よりモダンで機能的なバージョンの Memoize を書いています。

しかし、この質問に関連するように、関数の外側ではなく関数の内側からメモする方が便利な場合があります (Memoize は後者のみを行います)。これにより、キャッシュキーをカスタマイズしたり、この特定の呼び出しについてメモ化するかどうかを簡単に決定したりできます。例えば

sub complex_function {
    my $key = ...;   # normalize arguments
    if (...) {       # is it worth memoizing in this case?
        memoize_self({key => $key});
    }
}

ala state variablesの外側に独自の行を作成するのではなく、関数にラップされる方法も気に入っています。

4

4 に答える 4

7

Continuation::Escapeはまさにあなたが望むことを行います。ただし、Nikhil が指摘したように、Memoizeは本当に必要なものです。

于 2012-04-29T13:25:57.530 に答える
1

CPANモジュールMemoizeを見てください - 時間とスペースを交換して関数を高速化してください。これでおそらく問題が解決します。

于 2012-04-29T12:57:17.430 に答える
0

「発信者に戻るのではなく、発信者から戻る方法はありますか?」

はい、いくつかあります。

  • gotoジャンプバックに使用できます。を参照してくださいperldoc -f goto
  • と を使用evaldieて、よりコントロール ジャンプを行うことができます。perldoc -f evalおよびを参照してくださいperldoc -f die
  • 通常の方法でサブルーチンを呼び出す代わりに、それを行うことができgotoます。これを行うと、goto呼び出し元でサブに戻ります。を参照してくださいperldoc -f goto

もちろん、ほとんどの人は goto を避けるためにすべてを書き直し、コードを保守する人たちの生活を楽にするように言うでしょうが、彼らはあなたのために何をしてくれましたか?

于 2012-04-29T14:35:05.127 に答える
0

もう 1 つの解決策は、Want モジュールの double_return メソッドを使用することです。これにより、次のリターンが 2 つの呼び出しフレームからポップされます。

#!/usr/bin/env perl
use warnings;
use strict;

use Want;

sub foo {
    Want::double_return;
    return 11;
}
sub bar { 
    foo();
    # never executed
    return 55;
}

# prints 11;
print bar();
于 2012-04-29T17:50:17.170 に答える