なぜtbはすべての呼び出しで評価されるのですか?そして、それを一度だけ評価させる方法はありますか?
type test =
{ a: float }
member x.b =
printfn "oh no"
x.a * 2.
let t = { a = 1. }
t.b
t.b
ブライアンの回答の代替バージョンで、多くても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
それは財産です。あなたは基本的に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
ブライアンの投稿でのコメントに応じて、オプションの名前付き引数を使用して、レコード式をコピーして更新することができます。例えば:
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
前の応答は、レコードを使用する代わりに、クラスに切り替えることを提案しています。(単純な構文と不変性のために)レコードを保持したい場合は、次のアプローチを取ることができます。
type test =
{ a : float
b : float }
static member initialize (t: test) =
{ t with b = t.a * 2. }
test
これは、のインスタンスが別のライブラリ(Webサービスやデータベースのデータプロバイダーなど)によって作成されている場合に役立ちます。このアプローチでtest
は、コードで使用する前に、そのAPIから受け取ったインスタンスを初期化関数を介して渡すことを忘れないでください。