// Labels are separated by semicolons when defined on the same line. typePoint= { X:float; Y:float; Z:float; }
1 2
let mypoint = { X =1.0; Y =1.0; Z =-1.0; } mypoint
example2
1 2 3 4 5 6
// You can define labels on their own line with or without a semicolon. typeCustomer= { First:string Last:string; SSN:uint32 AccountNumber:uint32; }
example3
1 2 3 4
typePoint= { X:float; Y:float; Z:float; } typePoint3D= { X:float; Y:float; Z:float } // Ambiguity: Point or Point3D? let mypoint3D = { X =1.0; Y =1.0; Z =0.0; }
let myRecord3 = { myRecord2 with Y =100; Z =2 } myRecord3
example5
1 2 3 4 5 6 7 8
typeCar= { Make :string Model :string mutable Odometer :int }
let myCar = { Make ="Fabrikam"; Model ="Coupe"; Odometer =108112 } myCar.Odometer <- myCar.Odometer +21 myCar
example6
1 2 3 4 5 6 7 8 9 10 11 12
// Rather than use [<DefaultValue>], define a default record. typeMyRecord= { Field1 :int Field2 :int }
let defaultRecord1 = { Field1 =0; Field2 =0 } let defaultRecord2 = { Field1 =1; Field2 =25 }
// Use the with keyword to populate only a few chosen fields // and leave the rest with default values. let rr3 = { defaultRecord1 with Field2 =42 } rr3
example7
1 2 3 4 5 6 7 8 9 10 11
// Create a Person type and use the Address type that is not defined typePerson= { Name:string Age:int Address: Address } // Define the Address type which is used in the Person record and Address = { Line1:string Line2:string PostCode:string Occupant: Person }
example8
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// Create a Person type and use the Address type that is not defined letrec person = { Name ="Person name" Age =12 Address = { Line1 ="line 1" Line2 ="line 2" PostCode ="abc123" Occupant = person } } person
member this.WeirdToString() = this.Name + this.Address + string this.Age
let p = { Name ="a"; Age =12; Address ="abc123" } let weirdString = p.WeirdToString() weirdString
Differences Between Records and Classes
Record fields differ from class fields in that they are automatically exposed as properties, and they are used in the creation and copying of records. Record construction also differs from class construction. In a record type, you cannot define a constructor. Instead, the construction syntax described in this topic applies. Classes have no direct relationship between constructor parameters, fields, and properties.
Like union and structure types, records have structural equality semantics. Classes have reference equality semantics. The following code example demonstrates this.
1 2 3 4 5 6 7 8 9
typeRecordTest= { X:int; Y:int }
let record1 = { X =1; Y =2 } let record2 = { X =1; Y =2 }
if (record1 = record2) then printfn"The records are equal." else printfn"The records are unequal."
Anonymous Records
1 2 3 4 5 6 7 8 9 10 11 12 13
open System
let getCircleStats radius = let d = radius *2.0 let a = Math.PI * (radius **2.0) let c =2.0* Math.PI *radius
{| Diameter = d; Area = a; Circumference = c |}
let r =2.0 let stats = getCircleStats r printfn"Circle with radius: %f has diameter %f, area %f, and circumference %f" r stats.Diameter stats.Area stats.Circumference
Discriminated Unions
example
1 2 3 4
typeShape= | Rectangle of width :float* length :float | Circle of radius :float | Prism of width :float*float* height :float
1 2 3
let rect = Rectangle(length =1.3, width =10.0) let circ = Circle (1.0) let prism = Prism(5., 2.0, height =3.0)
let makeI3(x:int, y:float) = { new Interface3 with member this.Method3(i) = i +3+ x member this.Method2(i) = i +2+ x member this.Method1(i) = i +1+ x } let i = makeI3 (10, 1.0) i.Method1(5)