liveBook · Manning

Copy-and-update syntax

As explained in F# in Action: A Revised Edition of Get Programming with F#

Copy-and-update syntax is F# syntax that creates a record value by copying fields from an existing record and overriding or adding fields.

Copy-and-update syntax creates a new F# record from an existing value while changing selected fields. It is the usual answer when application data must appear to change over time but record fields remain immutable: the original value stays safe to share, and the changed state is represented by a new value. section 5.3.2 section 5.7

Write the source record before `with`, then list only the replacement fields. Unlisted fields are copied into the new record, so the code avoids manually rebuilding every field and makes the intended change explicit. section 5.3.2

Copy an address and change its location

Given `theAddress`, create `addressInDE` with `{ theAddress with Town = "Berlin"; Country = "DE" }`. The result has the changed town and country, while `theAddress` still represents the London, UK address. section 5.3.2

This is not field mutation. Using `<-` on an immutable record field produces a compiler error; copy-and-update instead records each change in a fresh value. A field can be declared `mutable` when necessary, such as for a record changed thousands of times per second in a tight loop, but immutable records are the recommended starting point until performance testing identifies a problem. section 5.3.2

Anonymous records extend the pattern: copy-and-update can override existing fields and add new ones at the same time. They suit exploration, scripts, one-off nested data, and mapping domain data into a JSON-shaped value, though they do not support inferred function-input types, attributes, or pattern matching. section 5.4.1

Listing 5.5 Using copy-and-update syntax to clone a record
let theAddress =                  #1
    {
        Line1 = "1st Street"
        Line2 = "Apt. 1"
        Town = "London"
        Country = "UK"
    }
let addressInDE =                 #2
    {
        theAddress with           #3
            Town = "Berlin"       #4
            Country = "DE"        #4
    }

Inspect a complete record literal and the compact copy that overrides only `Town` and `Country`. section 5.3.2

let companyWithBankDetails =
    {|
        company with
            AccountNumber = 123
            SortCode = 456
    |}

See an anonymous record copied from `company` while adding bank-detail fields. section 5.4.1

How F# in Action: A Revised Edition of Get Programming with F# covers it

How deep it goes
Explains record copying, field overrides, and mutable-field exceptions; notes anonymous-record additions and limitations.
Examples
Uses an Address copied from London to Berlin and an anonymous company record extended with bank details.
What it assumes
Uses record values and field names, while demonstrating copying with a small Address record.
What you can do after
Apply it to create changed record values without mutating the originals.
How it connects
Connects records and anonymous records with immutability, type inference, pattern matching, serialization, and JSON.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of F# in Action: A Revised Edition of Get Programming with F#. The section links point to the parts of the book it draws on.