F# 为什么闭包不能在成员函数上正常工作?

F# 为什么闭包不能在成员函数上正常工作?,f#,closures,F#,Closures,如果我正常操作,它将按预期工作并缓存结果: let help = let tmp = printfn "oh no" 1+1 fun () -> tmp help () help () >oh no 但是,如果我将其作为成员函数,它将不再工作: type test = { a: float } member

如果我正常操作,它将按预期工作并缓存结果:

      let help = let tmp = printfn "oh no"
                           1+1
                 fun () -> tmp
      help ()
      help ()

      >oh no
但是,如果我将其作为成员函数,它将不再工作:

    type test =
        { a: float }
        member x.help = 
                  let tmp = printfn "oh no"
                            x.a * 2.
                  fun () -> tmp
        member x.b = x.help ()

    let t = { a = 1. }
    t.b
    t.b

    >oh no
    >oh no

这才是真正的区别-

  let help = let tmp = printfn "oh no"
                       1+1
             fun () -> tmp
  printfn "here"
  help ()
  help ()
这张照片

here
oh no
所以实际上,帮助在被调用之前就已经形成了

在第二种情况下,我们可以阅读规范8.13.1

此外,以下两个成员是等效的:

staticopt成员标识。opt标识=expr

staticopt成员标识。get=expr的opt标识


也就是说,您的x.b实际上是一个每次调用帮助的函数

这是真正的区别-

  let help = let tmp = printfn "oh no"
                       1+1
             fun () -> tmp
  printfn "here"
  help ()
  help ()
这张照片

here
oh no
所以实际上,帮助在被调用之前就已经形成了

在第二种情况下,我们可以阅读规范8.13.1

此外,以下两个成员是等效的:

staticopt成员标识。opt标识=expr

staticopt成员标识。get=expr的opt标识


也就是说,你的x.b实际上是一个每次调用帮助的函数,

正如@John所说,根据,你的帮助属性相当于

type test =
     { a: float }
     member x.help with get () = 
              let tmp = printfn "oh no"
                        x.a * 2.
              fun () -> tmp
这是一个伪装的函数,因此每次调用属性时都会计算一个新的tmp值

要确保该属性只调用一次,您可以创建一个私人助手,并在类型扩充中使用它:

type test = { a: float }

/// Create a private helper to make sure 'help' is evaluate once
let private help = 
    printfn "oh no"              
    fun x -> x.a * 2.

/// Create a property using the private helper
type test with
     member x.b = help x

正如@John所说,根据,您的帮助属性相当于

type test =
     { a: float }
     member x.help with get () = 
              let tmp = printfn "oh no"
                        x.a * 2.
              fun () -> tmp
这是一个伪装的函数,因此每次调用属性时都会计算一个新的tmp值

要确保该属性只调用一次,您可以创建一个私人助手,并在类型扩充中使用它:

type test = { a: float }

/// Create a private helper to make sure 'help' is evaluate once
let private help = 
    printfn "oh no"              
    fun x -> x.a * 2.

/// Create a property using the private helper
type test with
     member x.b = help x

方法总是有一个隐式的this参数,所以它们总是函数。在您的例子中,x是OO代码中的一个参数,它在原始代码中不存在。

方法总是有一个隐式的this参数,因此它们总是函数。在您的例子中,x是OO代码中的一个参数,在原始代码中不存在。

一个值得指出的小错误,它应该在这里而不是这里打印哦不,没有一个值得指出的小错误,它应该在这里而不是这里打印哦不