1

如果我正常操作,它会按预期工作(缓存结果):

      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
4

3 回答 3

3

正如@John 所说,根据F# 规范,您的help属性相当于

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
于 2012-10-16T10:08:12.980 回答
2

这才是真正的区别——

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

这打印

here
oh no

所以帮助实际上在它被调用之前就已经形成了。

在第二种情况下,我们可以从规范(8.13.1)中读取

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

staticopt 成员 ident.opt ident = expr

staticopt 成员 ident.opt ident with get() = expr

即你的 xb 实际上是一个每次调用 help 的函数

于 2012-10-16T09:55:28.597 回答
0

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

于 2012-10-17T18:54:06.717 回答