liveBook · Manning

Declarative programming

As explained in The Joy of JavaScript

A style of programming that expresses the desired result rather than the step-by-step control flow used to compute it.

Declarative programming expresses the result and meaningful transformations while hiding control details such as loops, assignments, and state management. It favors code that reads like a description of the desired computation rather than instructions for the machine. section 4.2

Declarative code commonly emphasizes:

  • Unidirectional state transformations instead of explicitly describing every control-flow change. section 4.2
  • Named functions and expressions that reveal each processing step. section 4.3.1
  • Composition of small, pure functions that can be replaced or rearranged without changing results. section 4.3.1
  • A focus on what should be accomplished rather than how execution proceeds; SQL provides a prominent example. section 4.2

Composing a word counter

An imperative implementation reads a file, decodes its buffer, splits the text, and counts the words through explicit statements. A declarative version names those transformations and composes them: `const countWordsInFile = compose(count, split, decode, read);` The resulting function expresses the pipeline while hiding the intermediate control flow. section 4.3.1

function computeBalance(address) {
  let balance = Money.zero();
  for (const block of ledger) {
     if (!block.isGenesis()) {
        for (const tx of block.data) {
           if (tx.sender === address) {
              balance = balance.minus(tx.funds);
           }
           else {
              balance = balance.plus(tx.funds);
           }
        }
     }
  }
  return balance.round();
}

Compare the explicit loops, conditionals, assignments, and mutable balance state in the imperative calculation with its declarative counterpart. section 4.2

const computeBalance = address =>
 compose( 
   Money.round,
   reduce(Money.sum, Money.zero()),
   map(balanceOf(address)), 
   flatMap(prop('data')),
   filter( 
     compose( 
       not,
       prop('isGenesis')
     )
   ),
   Array.from
 );

Trace the same balance calculation as a composed pipeline of filtering, mapping, flattening, reducing, and rounding. section 4.2

How The Joy of JavaScript covers it

How deep it goes
Explains declarative flow through contrasts, composition, purity, and concrete pipelines, but defers framework-specific and formal language treatments.
Examples
Uses blockchain balance calculation, file word counting, SQL, and composed JavaScript functions as concrete examples.
What it assumes
Assumes JavaScript familiarity while developing higher-order functions, composition, purity, and immutability through examples.
What you can do after
Apply it via JavaScript function composition to express multi-step transformations with small, replaceable, single-responsibility functions.
How it connects
Connects declarative programming with imperative programming, functional programming, function composition, pure functions, immutability, and SQL.

Also explained in

Compare how 14 books explain declarative programming →

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.