Pau*_*ing 3 f# caching member memoization
我正在尝试记住一个类的成员函数,但每次调用该成员(由另一个成员)时,它都会创建一个全新的缓存和"memoized"函数.
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
Run Code Online (Sandbox Code Playgroud)
我在"真实世界功能编程"中使用清单10.5作为模型.我尝试过使用memoization高阶函数,但没有用.上面的列表直接内置了memoization.
问题是,当我称之为例如
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)
Run Code Online (Sandbox Code Playgroud)
执行进入'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))
Run Code Online (Sandbox Code Playgroud)
即使x.factorial的内部递归似乎也为每个级别设置了一个新的"缓存".
我做错了什么,我怎样才能做到这一点?
在回答你对杰克答案的评论时,这不必变得单调乏味.给出memoize功能:
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
Run Code Online (Sandbox Code Playgroud)
将每个函数定义为let-bound值并从方法中返回它们:
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
Run Code Online (Sandbox Code Playgroud)
唯一的"样板"是let绑定和调用memoize.
编辑:正如kvb所指出的,在F#3.0中,自动属性允许更简洁的解决方案:
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)
Run Code Online (Sandbox Code Playgroud)
我在这看到很多很长的答案; 简短的回答是
member x.P = code()
Run Code Online (Sandbox Code Playgroud)
定义一个P具有每次访问时运行的getter的属性.您需要将缓存创建移动到类的构造函数中,以便它只运行一次.code()P
| 归档时间: |
|
| 查看次数: |
754 次 |
| 最近记录: |