In ReasonML records allow for immutable updates using the spread operator, similar to copying case classes in Scala. This is also possible with objects, allowing the creation of immutable, but updatable, objects. In OCaml, these are known as functional objects.

Most ReasonML developers have come across the syntax below to update immutable records:

type cat = {name: string, age: int};

let kitten = { name: "Charles", age: 1 };

let oldCat = { ...kitten, age: 4 };

A similar technique exists for objects; however, it's not so well known amongst Reason developers, as I believe it is not included in the documentation. So at first, you might attempt something like the example below, which works but quickly becomes verbose as your records grow in size:

class immutableDog(name, age) = {
  as _;
  pub getAge: int = age;
  pub getName: string = name;
  pub setName: string => immutableDog = newName => new immutableDog(newName, age);
  pub setAge: int => immutableDog = newAge => new immutableDog(name, newAge);
};

Instead, you can override values to make a new instance with only the specified updates, similar to records. The syntax is not so obvious:

class immutableCat(name, age) = {
  as _;
  val name = name;
  val age = age;
  pub getAge: int = age;
  pub getName: string = name;
  pub setName = newName => {<name: newName>}; // Creates a new instance.
  pub setAge = newAge => {<age: newAge>};
};

This technique uses the override construct {< ... >}, which returns a copy of the current object and allows you to override the value of instance variables or methods.

Lets see what it looks like in action:

let myImmutableCat: immutableCat = new immutableCat("Cool Cat", 5);
let myNewCat: immutableCat = myImmutableCat#setName("Dave");
Oooh immutables!

Note that in the above example, myImmutableCat does not change.

It is also possible to update values in the same way:

class immutable = (number) => {
  as _;
  val counter = number * number;
  pub makeNegative = {<counter: -counter>};
  pub getCounter = counter;
};

let myImmutable = new immutable(4);
let negative = myImmutable#makeNegative;
myImmutable#getCounter // 4
negative#getCounter // -16
Yay more immutables!

Whilst this is a nice feature, the syntax could definately be improved and the functionality better documented.

And finally you're ready for the final part: row polymorphism and structural subtyping!