【问题标题】:let vs member in F#, need to clarify somethinglet vs member in F#,需要澄清一些事情
【发布时间】:2019-11-18 21:29:56
【问题描述】:

让我们考虑以下代码:

type RulesStore() =

    ...
    static member LoadAsync : Async<RulesStore> =
        async {
            let! r = Startup.States.GetAsStringAsync("rules") |> Async.AwaitTask

            return
                if String.IsNullOrEmpty r then
                    new RulesStore()
                else
                    JsonConvert.DeserializeObject<RulesStore>(r);
        }

这是对象内部的静态方法,用于从存储的 json 或新的干净 json 获取该对象的实例。

我是否相信如果我更换:

静态成员 LoadAsync : Async =

让 LoadAsync : Async =

LoadAsync 将被评估一次,随后的加载将返回相同的结果?如果我错了,这是为什么呢?

【问题讨论】:

    标签: f#


    【解决方案1】:

    这有点微妙。首先,您将let(实例)与static member(静态)进行比较,这增加了每个实例发生的事情与所有实例共享的事情之间的明显区别。

    更有用的比较是比较常规的memberlet。微妙的是async 计算本身是延迟的,所以它们只有在你执行它们时才会运行。

    以下是一个示例来说明这一点 - 我在 async 的定义之前添加了一个 printf 并在 async 块内添加了一个 letmember

    type A() = 
      let test = 
        printfn "let: before async"
        async { 
          printfn "let: inside async"
        }
      member x.Test =
        printfn "member: before async"
        async { 
          printfn "member: inside async"
        }
      member x.RunLet() = test |> Async.RunSynchronously
      member x.RunMember() = x.Test |> Async.RunSynchronously
    

    下面是代码的作用:

    let a = A() 
    // prints "let: before async"
    a.RunLet()  
    // prints "let: inside async"
    a.RunLet()  
    // prints "let: inside async"
    a.RunMember()  
    // prints "member: before async"
    // and "member: inside async"
    a.RunMember()  
    // prints "member: before async"
    // and "member: inside async"
    

    如您所见,每次调用异步计算时,“异步内部”的代码都会重复运行。但是,“异步之前”的代码对于 let 只运行一次,对于 member 重复运行。

    实际上,在异步之前您几乎没有代码,因此这在典型用途中没有太大区别,但有一些区别 - 使用 let,异步计算只构建一次,然后每次重用。

    【讨论】:

    • 好的,这证实了我的想法。感谢您提出一个澄清它的例子!
    猜你喜欢
    • 2012-07-20
    • 2021-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-29
    • 1970-01-01
    • 2020-07-25
    • 2013-08-06
    • 1970-01-01
    相关资源
    最近更新 更多