F#:尝试记住成员函数会在每次调用时重置缓存吗? [英] F#: Attempt to memoize member function resets cache on each call?
问题描述
我试图记住一个类的成员函数,但是每次(另一个成员)调用该成员时,它都会创建一个全新的缓存和"memoized"函数.
I'm trying to memoize a member function of a class, but every time the member is called (by another member) it makes a whole new cache and 'memoized' function.
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作为模型.我试过使用备忘录的高阶函数,但没有帮助.上面的清单具有直接内置的备注.
I'm using Listing 10.5 in "Real World Functional Programming" as a model. I've tried using a memoization higher-order function and that doesn't help. The above listing has the memoization built in directly.
问题是,当我称它为
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)行以确保它不是范围问题,但似乎不是.
execution goes to the 'let cache=...' line, defeating the whole point. I put in the (q2,l2) line in order to make sure it wasn't a scope problem, but it doesn't seem to be.
事实上,我使用Petricek的代码作为成员函数进行了测试,而且似乎存在相同的问题:
In fact I did a test using Petricek's code as a member function and that seems to have the same issue:
// 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的内部递归似乎也为每个级别建立了一个新的缓存".
Even the internal recursion of x.factorial seems to set up a new 'cache' for each level.
我在做什么错了,我该怎么做?
What am I doing wrong, and how can I make this work?
推荐答案
对于您对杰克回答的评论,这不必变得乏味.具备备忘录功能:
In response to your comment on Jack's answer, this doesn't have to become tedious. Given a memoize function:
let memoize f =
let cache = Dictionary()
fun x ->
match cache.TryGetValue(x) with
| true, v -> v
| _ ->
let v = f x
cache.Add(x, v)
v
将每个函数定义为让值,并从方法中返回它们:
Define each of your functions as let-bound values and return them from your methods:
type T() as x =
let internalDecRates = memoize <| fun (basis: Basis, tl: DateTime option) ->
(* compute result *)
Unchecked.defaultof<float * float>
let px = memoize <| fun (basis, tl) ->
let (q,l) = x.InternalDecRates(basis, tl)
let (q2,l2) = x.InternalDecRates(basis, tl)
(exp -q)*(1.-l)
member x.InternalDecRates = internalDecRates
member x.Px = px
唯一的样板"是let
绑定并调用memoize
.
The only "boilerplate" is the let
binding and call to memoize
.
如kvb所述,在F#3.0中,自动属性可提供更简洁的解决方案:
As kvb noted, in F# 3.0 auto-properties allow a more concise solution:
type T() as x =
member val InternalDecRates = memoize <| fun (basis: Basis, tl: DateTime option) ->
(* compute result *)
Unchecked.defaultof<float * float>
member val Px = memoize <| fun (basis, tl) ->
let (q,l) = x.InternalDecRates(basis, tl)
let (q2,l2) = x.InternalDecRates(basis, tl)
(exp -q)*(1.-l)
这篇关于F#:尝试记住成员函数会在每次调用时重置缓存吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!