F# 闭包:地图引用单元格始终为空
给出以下代码:
static member private getIntValue (_map:Map<string, int>) (_key:string) =
if (_map.ContainsKey _key) then
_map.[_key], _map
else
let i = doSomething ()
i, if i > 0 then _map.Add (_key, i) else _map
static member private getDataFn<'T> (_getFn:Map<string, 'T> -> string -> 'T * Map<string, 'T>) =
let dataMap = ref Map.empty
fun _key ->
let value, updatedMap = _getFn !dataMap _key
dataMap := updatedMap
value
static member getIndexNumber = getDataFn<int> getIntValue
... getDataFn<'T> 的函数定义第一行(即 fun _key -> ...)中 dataMap 引用单元格的值无论我调用 getIndexNumber 多少次,它始终为空(即 dataMap.Count = 0)。
显然,我希望每当将不存在的键传递给 getIndexNumber 时 dataMap 都会更新,但这并没有发生。每次都会将一个空 Map 传递给 getIntValue。
为什么会发生这种情况?
(PS,我知道我可以只使用字典,但这不是重点。)
Given the following code:
static member private getIntValue (_map:Map<string, int>) (_key:string) =
if (_map.ContainsKey _key) then
_map.[_key], _map
else
let i = doSomething ()
i, if i > 0 then _map.Add (_key, i) else _map
static member private getDataFn<'T> (_getFn:Map<string, 'T> -> string -> 'T * Map<string, 'T>) =
let dataMap = ref Map.empty
fun _key ->
let value, updatedMap = _getFn !dataMap _key
dataMap := updatedMap
value
static member getIndexNumber = getDataFn<int> getIntValue
... the value of the dataMap reference cell in the first line of the function definition (i.e. fun _key -> ...) of getDataFn<'T> is always empty (i.e. dataMap.Count = 0), no matter how many times I call getIndexNumber.
Obviously, I'm expecting dataMap to be updated whenever a non-existent key is passed to getIndexNumber, but this isn't happening. An empty Map is being passed to getIntValue every time.
Why is this happening?
(P.S. I know that I could just use a Dictionary, that's beside the point.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这里有一些代码可以解禁:
关键是
getIndexNumber
是一个属性,每次调用它时都会重新计算,最终每次都会调用getDataFn
,从而分配每次都有一个新的ref
。我将对getDataFn
的调用移至static let
中,因此它只被调用一次。不过,这段代码看起来非常不习惯。我可以建议更像这样的代码吗?
Here's some code to unblock you:
The key is that
getIndexNumber
is a property, which is re-evaluated each time it's called, which ends up callinggetDataFn
each time, which allocates a freshref
each time. I moved the call togetDataFn
into astatic let
so it only gets called once.This code all looks very un-idiomatic, though. Might I suggest code more like this?