我有一个GetCars函数,它不会返回更新后的状态。如果我添加一个参数,它工作正常,或者如果我在其他函数中执行相同的代码,它工作正常。
open System
open System.Collections.Concurrent
type Car = {
Make : string
Model : string
ID : int
}
type Cars = {
Count : int
Collection : Car[]
}
module AppState = begin
let state = new ConcurrentDictionary<string, obj>()
let added = state.TryAdd("cars", {
Count = 1
Collection = [| { Make = "Honda"; Model = "Civic"; ID = 0 } |]
})
let DownCastCars (o : obj) =
match o with
| :? Cars as cars -> Some(cars)
| _ -> None
let GetCars =
let mutable cars : obj = null;
let success = state.TryGetValue("cars", &cars)
if success then
DownCastCars cars
else
None
let AddCar car =
match GetCars with
| Some cars ->
state.TryUpdate("cars", { cars with Collection = Array.append cars.Collection [| car |] }, cars)
| None ->
false
end
let AddCarMakeModel make model =
let car : Car = {
Make = make
Model = model
ID = match AppState.GetCars with
| Some cars -> cars.Collection.Length
| None -> 0
}
let success = AppState.AddCar car
if success then
printfn "Successfully added car :)"
else
printfn "Failed to add car :("
[<EntryPoint>]
let main argv =
AddCarMakeModel "Honda" "Civic"
AddCarMakeModel "Honda" "Civic LX"
printfn "Press any key to continue"
let s = Console.ReadLine()
0 // return an integer exit code
如果我向GetCars添加一个参数,即
let GetCars notused =
let mutable cars : obj = null;
let success = state.TryGetValue("cars", &cars)
if success then
DownCastCars cars
else
None
然后GetCars函数每次都会返回最新值。或者,如果我只是将相同的代码放在我正在使用的其他方法中,即
let AddCarMakeModel Make Model =
let car : Car = {
Make = make
Model = model
ID = match AppState.GetCars with
| Some cars -> cars.Collection.Length
| None -> 0
}
let success = AppState.AddCar car
if success then
printfn "Successfully added car :)"
else
printfn "Failed to add car :("
我猜这与#34; Do Bindings&#34;但我不确定如何成功应用于GetCars。我确实注意到应用程序启动时会调用GetCars,如果我在函数内部设置了一个断点,它就再也没有了。
答案 0 :(得分:2)
正如评论中已经说明的那样,解决方案是添加一个单位参数。
问题在于您声明的是常量值,而不是函数值。
如果你看一下它的签名就很明显:val GetCars : Cars option
没有箭头,只有一个值,所以GetCars
只会被执行一次并绑定到表达式右侧的值
通过添加单位参数,您将获得签名:val GetCars : unit -> Cars option
所以现在在调用站点,您可以单独通过GetCars
引用函数值,或者执行它并通过{{获得结果1}}。
另请注意,您不需要mutable,因为F#将函数返回值并将ref作为元组处理,您可以像这样编写GetCars()
:
GetCars
然后摆脱函数let GetCars() =
match state.TryGetValue("cars") with
| true, (:? Cars as cars) -> Some cars
| _ -> None
。