liveBook · Manning

Copy-on-write

As explained in The Joy of JavaScript

A mutation strategy in which changes are made by creating modified copies rather than altering an existing value in place.

Copy-on-write changes data by returning a modified copy instead of altering the existing value. This preserves purity and makes value objects safer to compose. section 4.5

Immutable money operations

A Money value object can freeze its properties and have methods such as plus, minus, round, and asNegative return new Money objects. Thus, USD(3).plus(USD(7)) produces a separate USD(10), while the original values remain unchanged. section 4.5

Copy-on-write is useful when:

  • Value objects should behave immutably and avoid mutation-related bugs. section 4.5
  • Nested object updates should remain composable; lenses can target a property or path while handling copying automatically. section 4.5
Listing 4.13 Details of the Money value object
const BTC = 'B|';
 
const Money = curry((currency, amount) =>
  compose(                                                 #1
    Object.seal,
    Object.freeze
  )(Object.assign(Object.create(null),                     #2
    {
      amount,
      currency,
      equals: other => currency === other.currency &&
          amount === other.amount,
      round: (precision = 2) => 
          Money(currency, precisionRound(amount, precision)),
      minus: m => Money(currency, amount - m.amount),
      plus: m => Money(currency, amount + m.amount),
      times: m => Money(currency, amount * m.amount),
      compareTo: other => amount - other.amount,
      asNegative: () => Money(currency, amount * -1),
      valueOf: () => precisionRound(amount, 2),            #3
      toString: () => `${currency}${amount}`            
    }
  ))
);
 
// Zero
Money.zero = (currency = BTC) => Money(currency, 0);       #4
 
// Static helper functions
Money.sum = (m1, m2) => m1.add(m2);
 
Money.subtract = (m1, m2) => m1.minus(m2);
 
Money.multiply = (m1, m2) => m1.times(m2);
 
function precisionRound(number, precision) {
  const factor = Math.pow(10, precision);
  return Math.round(number * factor) / factor;
}

Inspect a Money implementation that combines frozen, sealed objects with methods using copy-on-write semantics. section 4.5

How The Joy of JavaScript covers it

How deep it goes
Defines return-new-object behavior and connects it to frozen value objects and lenses, without detailing lens implementation.
Examples
Uses Money arithmetic, frozen and sealed objects, and lenses for targeted immutable property updates.
What it assumes
Assumes familiarity with functional purity, composition, and custom objects while treating primitive immutability as given.
What you can do after
Apply it via value objects or lenses to update data without mutating existing values.
How it connects
Connects immutable objects with value objects, purity, functional programming, lenses, composition, and currying.

Also explained in

Compare how 5 books explain copy-on-write →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of The Joy of JavaScript. The section links point to the parts of the book it draws on.