Part of a series of posts explaining programming for the lay-person.
This is part of a series of posts; see the introduction to this series.
One of the most ambiguous and most important ideas in software development is the notion of different programming paradigms. The goal of all programs is to combine a lot of elementary expressions and statements into an unambiguous description of how to perform some larger task. A paradigm is something of a philosophy about how those combinations should be structured.
I doubt anyone could give a complete listing of programming paradigms. However, there are three basic categories of paradigms that have stood untouched for the last four or five decades: imperative, functional, and declarative or logic programming. Thus far, all successful paradigms have been built off of one of these three.
The imperative paradigm seems to be the most natural for most people. Recipes, assembly instructions, how-to guides, and driving directions are all written in an imperative style. Imperative programming is characterized by an ordered sequence of statements. It may contain subroutines, such as “prepare 2 pie crusts (see page 147)” and control structures Fear not, I shall discuss subroutines and control structures later. If these examples are confusing, don’t worry too much about it. such as “in high altitudes, preheat to 425°F instead” and “continue adding water by spoonfuls until it forms pea-sized lumps”. The guiding principal is that imperative programs explicitly tell you what to do next.
There are many derivations of imperative programming. Most “orientations” (object-oriented, aspect-oriented, etc) are designed around the imperative paradigm, though they can be applied elsewhere. One interesting extension that never caught on was Dijkstra’s “guarded statements”, where randomization is used to choose between several possible next steps.
The functional paradigm is something of a top-down approach. You don’t see much of it in daily life, but it shows up in a lot of mathematics. For example, “The cotangent of x is the multiplicative inverse of the tangent of x”, which begs the question, what’s a multiplicative inverse and what’s a tangent? Each of these will have similar definitions, which will require still further definitions, and so on until we get to something simple enough to actually do. Functional programming is characterized by a hierarchical combination of named expressions. It is also traditionally “stateless” or “purely functional”, meaning once you name a value it is fixed forever.
It is possible to compute anything using the functional paradigm, but silicon computers don’t really work in a functional way, so behind the scenes functional programs are transformed into imperative programs. However, it is easier to prove things about functional programs. Programming language theory is dominated by the functional paradigm.
Besides mathematics, the functional paradigm shows up in spreadsheet calculations and in a lot of “business logic”, like accounting and decision metrics.
The declarative or logical paradigm is the least used; indeed, if not for its historical importance it would likely not even be counted as a programming paradigm today. We see them today in logic or math puzzles: a list of facts, from which only one conclusion may be derived. That really is all you write when writing a declarative program, though care must be taken to make the facts in a form the computer can handle.
I could speak more about how to turn meaningful tasks into lists of horn clauses for a declarative program, but as I have not come up with a friendly way to do so and because declarative programming is quite rare I shall instead say only that it is locked to most professional programmers too and refrain from further efforts to unlock it.