0

「TheSeasonedSchemer」の第16章で、作成者は再帰的プロシージャ「depth」を定義します。これは、n個のリストにネストされたピザを返します。たとえば、(depth 3)is(((pizza)))。次に、setを使用して戻り値をキャッシュする「depthM」として改善します。リスト内のNsとRsは、一緒にルックアップテーブルを形成するため、前に見た戻り値に達した場合に、最後まで繰り返す必要はありません。たとえば、すでに計算した場合(depthM 8)、後で計算するときに(depthM 9)、(depthM 0)まで繰り返すのではなく、(depthM 8)の戻り値を検索し、nullに変換します。 。

しかし、その後、プロシージャ内でNとRを移動し、「let」を使用してnullに初期化します。なぜこれは戻り値をキャッシュするという点を完全に打ち負かさないのですか?少し実験したところ、「depthM」を呼び出すたびにNとRが再初期化されているようです。

私は彼らの主張を誤解していますか?

私の質問は本当にこれだと思います:「状態」変数を使ってPerl 5.10でできるように、字句スコープの変数がプロシージャの呼び出しの間に値を保持する方法はありますか?

4

1 に答える 1

5

当たり前。Seasoned Schemer を読んでいないので、ここでソース コードを提供しない限り、メモ化の問題についてコメントすることはできません。ただし、レキシカルスコープの変数が関数呼び出し間で状態を保持する方法があるかどうかという質問については...これは「クロージャー」と呼ばれるScheme言語の機能です。次の例を検討してください。

(define counter 
  (let ((number 0))
    (lambda () 
      (let ((result number))
        (set! number (+ number 1))
        result)))

このコードでは、number状態を追跡するためにレキシカル変数 ( ) を使用する counter という関数を定義しています。関数を呼び出すたびに、異なる数値が返されます。

> (counter)
0
> (counter)
1

等々。ここで重要な点は、lambda式の実行によって生成された関数が、囲んでいるスコープからレキシカルに見えるすべての変数を「閉じる」ことです (この場合のみnumber.)。つまり、これらの変数は、値を読み込んだり新しい値を書き込んだりする有効な場所のままです。に値します。

于 2010-04-05T14:58:13.787 に答える