F#记录会员评估

F#记录会员评估,f#,record,member,F#,Record,Member,为什么每次通话都要评估t.b?有没有办法让它只评估一次 type test = { a: float } member x.b = printfn "oh no" x.a * 2. let t = { a = 1. } t.b t.b 这是一种财产;您基本上是在调用get_b()成员 如果希望构造函数的效果只发生一次,可以使用一个类: type Test(a:float) = // constructor let b = // compute it

为什么每次通话都要评估t.b?有没有办法让它只评估一次

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

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

这是一种财产;您基本上是在调用
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

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

为了回应您在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

前面的回答建议切换到类,而不是使用记录。如果希望保留记录(因为它们的语法简单且不可变),可以采用以下方法:

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

如果
test
的实例是由另一个库(如来自web服务或数据库的数据提供程序)创建的,这将非常有用。使用这种方法,在代码中使用之前,必须记住通过initialize函数传递从该API接收的
test
的任何实例。

你是对的,但是使用类我会丢失一些东西,比如让c={t With a=4},对吗,但是你可以编写一个带有可选参数的构造函数,得到一个非常相似的效果。我不明白你的意思。假设我有一个记录,其中构造函数有10个参数,比如{a:float;b:float,c:float…}。从旧记录创建新记录的方式为{old with c=5}。如何在不重写构造函数中的所有参数的情况下对类执行相同的操作?令人失望的是,F#语言不支持对不可变记录的一次性计算值。我想复杂的是如果
a
被标记为可变的。你可以使用私有构造函数,这样你就不必记得调用initialize函数了。Scott Wlaschin在这里有一些例子: