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

布赖恩答案的替代版本,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()会员。

如果您希望效果在构造函数中发生一次,您可以使用一个类:

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

作为对您在 Brian 帖子中的评论的回应,您可以使用可选/命名参数来伪造复制和更新记录表达式。例如:

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 回答