Declarative Programming

Declarative programming means describing what a program must achieve (the facts, the relationships, what must hold) rather than how to achieve it, step by step. It is a spectrum, not a yes-or-no label: a language is more declarative the more of the execution it takes off your hands.

Three questions place a language on that spectrum:

  1. Expressions or statements? Does code compute values from its inputs, or change hidden state as it runs? x = x + 1 only makes sense if you know the machine's history; an expression over immutable values means the same thing every time.
  2. Who decides the control flow? Do you write the algorithm (look this up, then branch, then loop), or do you state the relationships and let an engine choose the order, the lookups and the data structures?
  3. Who manages the state? Do you thread state from one step to the next, or state which facts hold and let the language keep them?

On that scale:

  • Imperative languages (C, Java, Python) answer "you" to all three.
  • Functional languages, Erlang, Elixir and Gleam among them, are declarative on the first question: expressions over immutable values, no hidden mutation. That is why BEAM programmers rightly call them declarative. But you still write the algorithm, and you still thread the state through every call.
  • Relational and rule-based languages (SQL, Datalog, Prolog, Constraint Handling Rules) are declarative on all three. You describe the relationships and the constraints, and an engine works out the algorithm.

Bondy keeps the functional core the BEAM already has and adds the relational and rule-based part on top of it: relations queried in any direction, rules that fire when the facts they need are present, and constraints held in a store the language manages. That is the sense in which we call Bondy declarative: not in contrast to Erlang, but further along the same line.