F# - 函数不返回更新的数据

F# - Function not returning updated data

我有一个函数 GetCars,它没有 return 更新状态。如果我添加一个参数,它可以正常工作,或者如果我在其他函数中执行相同的代码,它也可以正常工作。

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 函数每次都会 return 最新的值。或者,如果我只是将相同的代码放在我正在使用的其他方法中,即

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 :("

我猜这与 "Do Bindings" 有关,但我不确定如何将其成功应用于 GetCars。我注意到 GetCars 在应用程序启动时被调用,如果我在函数内设置断点,它就再也不会那么远了。

如评论中所述,解决方案是添加一个单位参数。

问题是您声明的是常量值,而不是函数值。

看签名就知道了:val GetCars : Cars option没有箭头,只有一个值,所以GetCars只会执行一次,绑定到右边的值表达式。

通过添加一个单元参数,您可以获得签名:val GetCars : unit -> Cars option 所以现在在调用站点,您可以单独通过 GetCars 引用函数值,或者执行它并通过GetCars().

另请注意,您不需要可变变量,因为 F# 将返回值和引用的函数视为元组,您可以这样写 GetCars

let GetCars() = 
    match state.TryGetValue("cars") with
    | true, (:? Cars as cars) -> Some cars
    | _ -> None

然后去掉函数DownCastCars