F#:尝试记住成员函数会在每次调用时重置缓存吗? [英] F#: Attempt to memoize member function resets cache on each call?

查看:75
本文介绍了F#:尝试记住成员函数会在每次调用时重置缓存吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图记住一个类的成员函数,但是每次(另一个成员)调用该成员时,它都会创建一个全新的缓存和"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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆