クラスのメンバー関数をメモ化しようとしていますが、メンバーが (別のメンバーによって) 呼び出されるたびに、まったく新しいキャッシュと「メモ化された」関数が作成されます。
member x.internal_dec_rates =
let cache = new Dictionary< Basis*(DateTime option), float*float>()
fun (basis:Basis) (tl:DateTime option) ->
match cache.TryGetValue((basis,tl)) with
| true, (sgl_mux, sgl_lps) -> (sgl_mux, sgl_lps)
| _ ->
let (sgl_mux, sgl_lps) =
(* Bunch of stuff *)
cache.Add((basis,tl),(sgl_mux,sgl_lps))
sgl_mux,sgl_lps
「実世界の関数型プログラミング」のリスト 10.5 をモデルとして使用しています。メモ化の高階関数を使用してみましたが、役に立ちません。上記のリストには、メモ化が直接組み込まれています。
問題は、私がそれを呼び出すときです。
member x.px (basis:Basis) (tl: DateTime option) =
let (q,l) = (x.internal_dec_rates basis tl)
let (q2,l2) = (x.internal_dec_rates basis tl)
(exp -q)*(1.-l)
実行は「let cache=...」行に進み、ポイント全体を無効にします。スコープの問題ではないことを確認するために (q2,l2) 行を挿入しましたが、そうではないようです。
実際、メンバー関数として Petricek のコードを使用してテストを行ったところ、同じ問題があるようです。
// Not a member function
let memo1 f =
let cache = new Dictionary<_,_>()
(fun x ->
match cache.TryGetValue(x) with
| true, v -> v
| _ -> let v = f x
cache.Add(x,v)
v
)
member x.factorial = memo1(fun y->
if (y<=0) then 1 else y*x.factorial(y-1))
x.factorial の内部再帰でさえ、レベルごとに新しい「キャッシュ」を設定しているようです。
私は何を間違っていますか、どうすればこれを機能させることができますか?