为什么每次通话都会评估t.b?有没有办法让它只评估一次?
type test =
{ a: float }
member x.b =
printfn "oh no"
x.a * 2.
let t = { a = 1. }
t.b
t.b
答案 0 :(得分:15)
Brian的答案的替代版本,最多只能评估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
答案 1 :(得分:13)
这是一个财产;你基本上是在呼叫get_b()
成员。
如果希望效果在构造函数中发生一次,则可以使用类:
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
答案 2 :(得分:4)
回应你在Brian的帖子中的评论,你可以使用optional / named args伪造复制和更新记录表达式。例如:
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
答案 3 :(得分:1)
之前的回复建议切换到班级,而不是使用记录。如果你想保留记录(因为它们的语法和不变性),你可以采用这种方法:
type test =
{ a : float
b : float }
static member initialize (t: test) =
{ t with b = t.a * 2. }
如果test
的实例由另一个库(如来自Web服务或数据库的数据提供程序)创建,则此选项非常有用。使用此方法,您必须记住在代码中使用之前,通过初始化函数传递从该API收到的test
的任何实例。