Does updating an immutable record field always create a new object?

If I have a record

type t = {name: string; age: int}

and the variable r is of type t, is it guaranteed that the expression

{r with name = "Ronald"}

creates a new object i.e. is

assert (not (r == {r with name = "Ronald"}))

valid or is it possible that some optimizer in the compiler finds out that the old object is no longer used and therefore just overwrites the field name in r?

It is not possible to reuse an object that isn’t used anymore at the moment (although there are plans to do that in OxCaml in some cases).

However, if you have the following code:

type t = {name: string; age: int}

let r1 = { name = "Ronald"; age = 99 }
let r2 = { r1 with name = "Ronald" }
let test = (r1 == r2)

The value of test here is not specified, and in practice can differ between ocamlc and ocamlopt.

Such an optimization isn’t implemented, no. But if it ever does, it wouldn’t be observable with r == {r with name = "Ronald"} because then you’d be using the old value, which would disable the optimization.

As for why it isn’t implemented, other than effort: Mutating pointers to the heap isn’t free in GC runtimes. It involves a write barrier, which means allocating a new object can sometimes be faster than mutating an existing one, at the expense of GC pressure. Since there is a trade-off involved, such an optimization would need to make sure it only ever triggers when it’s a net benefit.

If you’ve seen this optimization in other research languages, it most likely was one with reference counting instead of a tracing GC, like Koka or Lean, which also benefit from inspecting the ref-count at runtime rather than relegating this to a compile-time optimization.

1 Like

In the actual default OCaml compiler, this is not possible. In the modified version of OCaml that uses the Perceus ‘garbage-free’ reference-counting algorithm, this is exactly what happens. Of course, that modified version is a proof of concept only. It’s not a production-grade project.

There is also a similar optimisation in the compiler for the https://en.wikipedia.org/wiki/Clean\_(programming_language) programming language which uses “uniqueness types”, where a value can be updated in-place (and eventually deallocated at some point which is determined at compile-time), but I don’t know many languages with the same feature. (I think this is actually a feature which OxCaml introduces.)

General functional programming is more ergonomic than uniqueness types, so there is a trade-off.

Thank you all for the great hints.