Set record property when creating instance

Viewed 68

I have a record type

type Record = { Start: DateTime; End: DateTime; Duration: TimeSpan }
let record = { Start = DateTime.Now; End = DateTime(2021,12,1) }

This code won't compile as there's no assignment given for field Duration.

Is it possible to calculate Duration in the type definition instead of assigning it?

3 Answers

Solved it:

type Record = { Start: DateTime; End: DateTime; }
with
  member this.Duration = this.End - this.Start

let record = { Start = DateTime.Now; End = DateTime(2021,12,1) }

If you don't want to recompute Duration every time it's called, you can do something like this:

type Record = private { Start: DateTime; End: DateTime; Duration: TimeSpan }

let create startTime endTime =
    {
        Start = startTime
        End = endTime
        Duration = endTime - startTime
    }

let record = create DateTime.Now (DateTime(2021,12,1))

Note that I've made the fields private, so users will be forced to call create. The only downside of this approach is that users can no longer access the fields at all, so you might want to provide separate accessors for them:

type Record = private { _Start: DateTime; _End: DateTime; _Duration: TimeSpan } with
    member this.Start = this._Start
    member this.End = this._End
    member this.Duration = this._Duration

let create startTime endTime =
    {
        _Start = startTime
        _End = endTime
        _Duration = endTime - startTime
    }

let record = create DateTime.Now (DateTime(2021,12,1))

This too will not recalculate Duration. It's not a record though.

type MyClass(startTime, endTime) =
    member val Start: DateTime = startTime
    member val End: DateTime = endTime
    member val Duration: TimeSpan = endTime - startTime

let myObject = MyClass(DateTime.Now, DateTime(2021,12,1))

But I wouldn't go to this much trouble just to avoid the recalculation, unless it was time critical. That goes for the other answers too.

Related