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、プロパティが呼び出されるたびに新しい値が評価されます。

プロパティが 1 回呼び出されるようにするために、プライベート ヘルパーを作成し、それを型拡張で使用できます。

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

そのため、ヘルプは呼び出される前に実際に形成されます。

2 番目のケースでは、仕様 (8.13.1) から読み取ることができます。

さらに、次の 2 つのメンバーは同等です。

staticopt メンバ ident.opt ident = expr

staticopt メンバ ident.opt ident with get () = expr

つまり、あなたの xb は実際には毎回 help を呼び出す関数です

于 2012-10-16T09:55:28.597 に答える
0

メソッドには常に暗黙のthis引数があるため、常に関数です。あなたの場合x、元には存在しなかったオブジェクト指向コードの引数です。

于 2012-10-17T18:54:06.717 に答える