Structured Programming introduced the notion of nesting control flow with constructs like if-then-else, while, etc.

Object-Oriented Programming popularized the notion of nesting data via inhertiance.

OOP and Structure Programming do not fully isolate control-flow. CALL / RETURN is usually supported in hardware by a global variable (the Stack).

CALL / RETURN violates the single-entry-single-exit edict of Structured Programming. Programmers can CALL subroutines directly and “break through” the boundaries of a properly structured

To enable software construction using components, we must fully isolate data and control-flow.

Threads for Isolation of Control Flow

Threads, common in desktop operating systems like Linux, MacOS and Windows, isolate control flow in a heavy-handed manner. Threads often employ full-preemption and hardware MMUs.

Full preemption has caused a great deal of accidental complexity, e.g. the Mars Rover disaster.

Fixes for known problems have been developed, but it is clear that full preemption inhibits reasoning about designs.

Pure Functions for Isolation of Control Flow

FP restricts programs by expunging mutability to achieve isolation.

These kinds of languages severely restrict the programming paradigm(s) that can be employed to solve practical problems.

Calculators - One Input One Output

FP makes it easy to treat computers as calculators.

FP assumes that all functions have one block of inputs and one block of outputs.

FP is not well-suited to solving problems using paradigms that exceed this simple model.

Exceptions

For example, exceptions are usually treated as edge-cases with second-class syntax and second-class semantics.

Javascript

Javascript was invented for creating distributed programs (aka web pages).

Javascript continues to use function-like syntax with the result that simple distributed operations need to be programmed as callbacks.

Referential Transparency

An ideal for component-based design is the ability to replace components with pin-compatible ones.

In hardware design, this was called pin compatibility.

In functional progamming languages, this is called referential transparency.

FP languages achieve referential transparency by restricting the language paradigm that can be used.

FP expunges mutability and mutable operations.

(Note that this is not the only way to achieve referential transparency. A different solution was developed in the electronics industry in the 1950’s).

Hidden Dependencies - Global Variables

A major factor in the complexity of computer systems is the hidden dependencies between modules and the hardware-supported used of a global Stack.

Earlier computers, e.g. the IBM 360, did not have a hardware-supported Stack (programmers had to simulate a Stack using the BALR instruction).

Hidden Dependencies - Synchrony vs. Asynchrony

Most languages use a sequential function paradigm.

This sequential model resists the natural paradigm for computing - asynchronous operation.

It should be noted that asynchrony is common in human experience

  1. the human body contains an autonomous nervous system which consists of some 500 independent units
  2. children around the age of 5 learn to use a hard, real-time notation
  3. businesses run in a top-down manner (aka Org Charts) and consist of many independent units.

Concurrency

— spaghetti
— The Stack
— Scalability
— Superposition

See Also

References
Table of Contents