给出以下代码:
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&lt;'T&gt;的函数定义的第一行(即fun _key - &gt; ...)中的dataMap引用单元格的值。无论我多少次调用getIndexNumber,它总是空的(即dataMap.Count = 0)。
显然,我希望每当将不存在的密钥传递给getIndexNumber时都会更新dataMap,但这不会发生。每次都会将空Map传递给getIntValue。
为什么会这样?
(P.S。我知道我可以使用一个字典,这不是重点。)
答案 0 :(得分:3)
以下是一些解锁您的代码:
let doSomething() = 2
type Foo() =
static let indexer = Foo.getDataFn<int> Foo.getIntValue
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>) : (string -> 'T)=
let dataMap = ref Map.empty
fun _key ->
printfn "count = %d" (!dataMap).Count
let value, updatedMap = _getFn !dataMap _key
dataMap := updatedMap
value
static member getIndexNumber = indexer
// static member getIndexNumber = Foo.getDataFn<int> Foo.getIntValue
let r = Foo.getIndexNumber("foo")
printfn "%d" r
let r2 = Foo.getIndexNumber("foo")
printfn "%d" r2
关键是getIndexNumber
是一个属性,每次调用时都会重新评估,最后每次调用getDataFn
,每次都会分配一个新的ref
。我将调用移至getDataFn
进入static let
,因此只会调用一次。
但这段代码看起来都非常不恰当。我可以建议更像这样的代码吗?
let doSomething() = 2
type StringIndexer() =
let mutable map : Map<string,int> = Map.empty
let get(s) =
printfn "count = %d" map.Count
match map.TryFind s with
| None ->
let i = doSomething()
map <- map.Add(s,i)
i
| Some(i) -> i
member this.GetIndexNumber(s) = get(s)
let si = new StringIndexer()
let r = si.GetIndexNumber("foo")
printfn "%d" r
let r2 = si.GetIndexNumber("foo")
printfn "%d" r2