Ship

Book · Updating records

Updating records

Draft

Replace fields immutably, or assign mut fields in place.

On this page · 2 sections

Immutable updates

{ value with ... } replaces selected fields and keeps the original type. The source record is unchanged.

type Digest = [
  | :daily
  | :weekly
]

type Profile = {
  display_name: String;
}

type EmailSettings = {
  digest: Digest;
}

type Settings = {
  email: EmailSettings;
}

type User = {
  id: Int;
  name: String;
  profile: Profile;
  settings: Settings;
}

let renamerename: fn(user: Book.Records.UpdatingRecords.User, name: String) -> Book.Records.UpdatingRecords.User = (useruser: Book.Records.UpdatingRecords.User, namename: String) =>
  { useruser: Book.Records.UpdatingRecords.User with name = namename: String; };

Record Updates

test✓
  let adaada: Book.Records.UpdatingRecords.User = User {
    id = 11: Int;
    name = "Ada""Ada": String;
    profile = Profile { display_name = "ada""ada": String; };
    settings = Settings { email = EmailSettings { digest = :daily; }; };
  };
  expect ✓adaada: Book.Records.UpdatingRecords.User == User {
    id = 11: Int;
    name = "Ada""Ada": String;
    profile = Profile { display_name = "ada""ada": String; };
    settings = Settings { email = EmailSettings { digest = :daily; }; };
  };

  ✓renamerename: fn(user: Book.Records.UpdatingRecords.User, name: String) -> Book.Records.UpdatingRecords.User: fn(User, String) -> User;
  let gracegrace: Book.Records.UpdatingRecords.User = renamerename: fn(user: Book.Records.UpdatingRecords.User, name: String) -> Book.Records.UpdatingRecords.User(adaada: Book.Records.UpdatingRecords.User, "Grace""Grace": String);
  expect ✓gracegrace: Book.Records.UpdatingRecords.User == User {
    id = 11: Int;
    name = "Grace""Grace": String;
    profile = Profile { display_name = "ada""ada": String; };
    settings = Settings { email = EmailSettings { digest = :daily; }; };
  };

  //! Dotted paths update nested stored fields. Expanded entries sit one level
  //! beneath `value with`.
  let personalizedpersonalized: Book.Records.UpdatingRecords.User = {
    adaada: Book.Records.UpdatingRecords.User with
      profile.display_name = "teej""teej": String;
      settings.email.digest = :weekly;
  };
  expect ✓personalizedpersonalized: Book.Records.UpdatingRecords.User == User {
    id = 11: Int;
    name = "Ada""Ada": String;
    profile = Profile { display_name = "teej""teej": String; };
    settings = Settings { email = EmailSettings { digest = :weekly; }; };
  };

Dotted paths update nested stored fields. Expanded entries sit one level beneath value with.

Mutable fields

Mark a field mut to assign it with :=. Other fields stay immutable. := yields the right-hand side, so bump returns Int. Locals, shadowing, and more assignment forms are in mutability.

type Counter = {
  mut value: Int;
  label: String;
}

let bumpbump: fn(counter: Book.Records.UpdatingRecords.Counter) -> Int = (countercounter: Book.Records.UpdatingRecords.Counter) => counter.value := countercounter: Book.Records.UpdatingRecords.Counter.valuevalue: Int + 11: Int;

Mutable Fields

test✓
  ✓bumpbump: fn(counter: Book.Records.UpdatingRecords.Counter) -> Int: fn(Counter) -> Int;
  let countercounter: Book.Records.UpdatingRecords.Counter = Counter { value = 00: Int; label = "hits""hits": String; };
  expect ✓bumpbump: fn(counter: Book.Records.UpdatingRecords.Counter) -> Int(countercounter: Book.Records.UpdatingRecords.Counter) == 11: Int;
  expect ✓countercounter: Book.Records.UpdatingRecords.Counter == Counter { value = 11: Int; label = "hits""hits": String; };