liveBook · Manning

Functional, stateless philosophy

As explained in The Joy of JavaScript

A programming paradigm that models computation as the evaluation of functions, often emphasizing immutability and function composition.

Functional programming treats functions as computations to combine, rather than commands that repeatedly change shared state. A pure function produces the same result for the same input, leaves existing state unchanged, and returns a new value instead of mutating its input. section 4.1 section 4.1.2

This changes how a problem is described. Imperative code specifies loops, branches, and assignments; functional code describes a flow of transformations. Higher-order functions make that flow possible by accepting functions as callbacks, while composition connects one function’s output to the next function’s input. section 1.3 section 4.2

Useful rules for a stateless calculation:

  • Pass required data as arguments, or obtain it from a closure that follows the same rules. section 4.1.2
  • Return a value without changing observable application state; equal inputs should produce equal outputs. section 4.1.2
  • Keep effects such as console output, filesystem access, and network writes outside the pure calculation. section 4.1.2

From a running balance to a data flow

A wallet balance can be computed by filtering out the genesis block, flattening the remaining transactions, mapping each transaction to its contribution, and reducing those contributions to a total. Unlike nested loops that reassign a running balance, the transformation passes results between operations. The Wallet method can still exist: it delegates to computeBalance(this.address, ledger), keeping object access at the boundary of the calculation. section 4.7

Listing 4.15 Calculating balance in Wallet with FP
function computeBalance(address, ledger) {
   return Array.from(ledger)                   #1
    .filter(not(prop('isGenesis')))            #2
    .map(prop('data'))                         #3
    .flat()                                    #4
    .map(balanceOf(address))                   #5
    .reduce(Money.sum, Money.zero())           #6
    .round();                                  #8
}

Follow the array operations in the worked balance calculation to see how filtering, flattening, mapping, and reducing replace nested loops and reassignment. section 4.7

Composition can shorten that chain further, though compose orders the written functions opposite to the direction data flows. A pipe expresses them left to right. The native |> pipeline operator is presented as a proposed feature, not as a requirement for this style. section 4.7 section 4.8

How The Joy of JavaScript covers it

How deep it goes
Defines purity and works through a wallet-balance refactoring, while leaving broader functional programming beyond this treatment.
Examples
Uses block validation with filter, map, and reduce, then refactors a wallet-balance calculation from nested loops into an array pipeline.
What it assumes
Assumes familiarity with imperative functions and uses familiar JavaScript array operations to introduce functional reasoning.
What you can do after
Practice/perform a refactoring that extracts a pure balance calculation while retaining a delegating Wallet method.
How it connects
Connects higher-order functions, immutability, closures, referential transparency, currying, and function composition.

Also explained in

Compare how 19 books explain functional, stateless philosophy →

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.