Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / All-Topics

F#7 : Records

5.00/5 (1 vote)
22 May 2014CPOL3 min read 16.4K  
So we continue our journey into more of the F# types. This time we will be looking at Record types.   How Do I Create A Record When you create a new F# record, it may remind you of anonymous objects in C#. Here is how you create them. I think they are quite similar […]

So we continue our journey into more of the F# types. This time we will be looking at Record types.

How Do I Create A Record

When you create a new F# record, it may remind you of anonymous objects in C#. Here is how you create them. I think they are quite similar to anonymous objects in C#, so if you have used C#, F#s records should not be that hard to get into.

It starts by creating a new type for the record. The type definition lists the name of the properties and also the type of the properties, this can be seen below.

Once you have a record type definition you re free to bind a new instance to a value use Let. Again an example of this can be seen below, where we bind a new record using a Let binding, and we also print the property values of the record instance to the console output.

C#
type Person = { Age : int; Sex: string; Name:string; }  
....
....
....
....
let sam = { Age = 12; Sex="Male"; Name ="Sam" }
printfn "let sam = { Age = 12; Sex=\"Male\"; Name=\"Sam\" }" 
printfn "Person with Age is %i and Sex is %s and Name is %s" sam.Age sam.Sex sam.Name

which gives this result

image

How Do I Alter/Clone A Record

You are able to clone and alter a record, which is typical done as follows:

C#
//clone and alter sam to become new Person tom
let sam = { Age = 12; Sex="Male"; Name ="Sam" }
let tom = { sam with Name="Tom" }
printfn "let tom = { sam with Name=\"Tom\" }" 
printfn "Person with Age is %i and Sex is %s and Name is %s" tom.Age tom.Sex tom.Name

Which gives this result

image

Note how we used the “with” keyword when creating the new tom person instance. This form of the record expression is called the “copy and update record expression”. Another choice you could use (again we will be covering this in more detail in a later post) is use a mutable property in your record type. Records are immutable by default; however, you can also explicitly specify a mutable field.

Here is an example, notice how I have created a new type which has a mutable property called MutableName. By defining a mutable field, I am allowed to update the value of the MutableName property of the record, which you can do using the “<-“ operator. Which simply allows a new value to be assigned.

C#
type MutableNamePerson = { Age : int; Sex: string; mutable MutableName:string; }   
....
....
....
....
//create
let sam = { Age = 12; Sex="Male"; MutableName ="Sam" }
printfn "let sam = { Age = 12; Sex=\"Male\"; Name=\"Sam\" }" 
printfn "Person with Age is %i and Sex is %s and Name is %s" sam.Age sam.Sex sam.MutableName
//update
sam.MutableName <- "Name changed"
printfn "sam.MutableName <- \"Name changed\"" 
printfn "Person with Age is %i and Sex is %s and Name is %s" sam.Age sam.Sex sam.MutableName

Which has this result

image

Record Equality

Record types are only equal if ALL the properties are considered the same. Here is an example

C#
type Person = { Age : int; Sex: string; Name:string; }   
....
....
....
....
let someFunction p1 p2 =
    printfn "p1=%A, and p2=%A, are they equal %b" p1 p2 (p1=p2)


let sam =  { Age = 12; Sex = "Male"; Name = "Sam" }
let john = { Age = 12; Sex = "Male"; Name = "John" }
let april = { Age = 35; Sex = "Female"; Name = "April" }
let sam2 = { Age = 12; Sex = "Male"; Name = "Sam" }
do someFunction sam john
do someFunction sam april
do someFunction sam sam2

And here is the result

image

Pattern Matching Records

It is of course possible to use pattern matching (a discussion for another day), which is a core F# technique, to match against Record types. Here is an example

C#
type Person = { Age : int; Sex: string; Name:string; }  
.....
.....
.....
.....
let someFunction (somePerson :Person) =
    match somePerson with
    | { Name="Sam" }    -> printfn "Sam is in the house"
    | _                 -> printfn "you aint Sam, get outta here clown"


let sam = { Age = 12; Sex="Male"; Name ="Sam" }
let john = { Age = 12; Sex="Male"; Name ="John" }
do someFunction sam
do someFunction john

Which has the result

image

Methods And Properties

It is also possible to add extra members to records. Here is an example where we add a “Details” property to allow the full details of the record to be obtained by using a single property (much as the we could achieve by overriding the ToString() method, but more on OO techniques later on ok)

Note that if you tried to add a member to the record type definition as shown in this screen shot you will get a strange error

image

This is easily solved by simply putting the record property definitions on a new line, and making sure the member starts on a new line too, and watch that indenting (whitespace), as it is all important in F#

C#
type Person = 
    { Age : int; Sex: string; Name:string; }   
    member this.Details = this.Age.ToString() + " " + this.Sex.ToString() + " " + this.Name
....
....
....
....
let sam =  { Age = 12; Sex = "Male"; Name = "Sam" }
printfn "sam Details=%s" sam.Details

Which has the result

image


License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)