Why is t.b evaluated on every call? And is there any way how to make it evaluate only once?
type test =
{ a: float }
member x.b =
printfn "oh no"
x.a * 2.
let t = { a = 1. }
t.b
t.b
An alternative version of Brian's answer that will evaluate b
at most once, but won't evaluate it at all if B
is never used
type Test(a:float) =
// constructor
let b = lazy
printfn "oh no"
a * 2.
// properties
member this.A = a
member this.B = b.Value
The previous responses suggest switching to a class, instead of using a record. If you want to stay with records (for their simple syntax and immutability), you can take this approach:
type test =
{ a : float
b : float }
static member initialize (t: test) =
{ t with b = t.a * 2. }
This is useful if the instance of test
is created by another library (like a data provider from a web service or database). With this approach, you must remember to pass any instance of test
that you receive from that API through the initialize function before using it in your code.
It's a property; you're basically calling the get_b()
member.
If you want the effect to happen once with the constructor, you could use a class:
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
In response to your comments in Brian's post, you can fake copy-and-update record expressions using optional/named args. For example:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With