13

なぜtbはすべての呼び出しで評価されるのですか?そして、それを一度だけ評価させる方法はありますか?

type test =
  { a: float }
  member x.b =
    printfn "oh no"
    x.a * 2.

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

4 に答える 4

16

ブライアンの回答の代替バージョンで、多くても1回は評価されますが、使用されないb場合はまったく評価されません。B

type Test(a:float) =
    // constructor
    let b = lazy
                 printfn "oh no"
                 a * 2.
    // properties
    member this.A = a
    member this.B = b.Value
于 2010-05-20T12:02:37.993 に答える
13

それは財産です。あなたは基本的にget_b()メンバーを呼んでいます。

コンストラクターで効果を1回発生させたい場合は、次のクラスを使用できます。

type Test(a:float) =
    // constructor
    let b =   // compute it once, store it in a field in the class
        printfn "oh no"
        a * 2.
    // properties
    member this.A = a
    member this.B = b
于 2010-05-20T11:20:35.617 に答える
4

ブライアンの投稿でのコメントに応じて、オプションの名前付き引数を使用して、レコード式をコピーして更新することができます。例えば:

type Person(?person:Person, ?name, ?age) =

    let getExplicitOrCopiedArg arg argName copy =
        match arg, person with
        | Some(value), _ -> value
        | None, Some(p) -> copy(p)
        | None, None -> nullArg argName

    let name = getExplicitOrCopiedArg name "name" (fun p -> p.Name)
    let age = getExplicitOrCopiedArg age "age" (fun p -> p.Age)

    member x.Name = name
    member x.Age = age

let bill = new Person(name = "Bill", age = 20)
let olderBill = new Person(bill, age = 25)

printfn "Name: %s, Age: %d" bill.Name bill.Age
printfn "Name: %s, Age: %d" olderBill.Name olderBill.Age
于 2010-05-21T19:39:37.117 に答える
2

前の応答は、レコードを使用する代わりに、クラスに切り替えることを提案しています。(単純な構文と不変性のために)レコードを保持したい場合は、次のアプローチを取ることができます。

type test =
    { a : float
      b : float }
    static member initialize (t: test) =
        { t with b = t.a * 2. }

testこれは、のインスタンスが別のライブラリ(Webサービスやデータベースのデータプロバイダーなど)によって作成されている場合に役立ちます。このアプローチでtestは、コードで使用する前に、そのAPIから受け取ったインスタンスを初期化関数を介して渡すことを忘れないでください。

于 2014-11-03T04:11:18.190 に答える