In contrast to the usual imperative languages (e.g., C, Fortran, and Ada), in which variables represent cells in memory that can be modified using the assignment operator = (or :=), functional languages view the use of the = operator as an expression of an equation. For example, if a functional program contains the declaration let x = f(y) then this would introduce the name x and assert that the equation x = f(y) is true. There is no notion of a memory cell, and certainly no notion that somehow later in the program x might change (so that the equation would become false) – Goldberg, Functional Programming Languages, AMC Computing Surveys, March 1996.
Here’s a common mathematical expression
\(y = \Sigma_{x=1}^{x=10}x\)
The value of “x” changes from 1 to 10. Here’s part of the description from the great text by Aleksandrov, Kolmmogrov, and Lavrent’ev survey of mathematics chapter on Approximate Calculation of Roots.
\( \gamma_1 = – \frac{(b-a)fa(a)}{f(b)-f(a) +a }.\)
Taking this number for the new b in cases I and II and for the new a in cases II and IV we find …
This “new b” is not the same as the old b. And it’s not just in Soviet era Rusian math texts that we find such heretical material. Even in Abstract Algebra texts, we can find texts where “Let x be an element of the group G” later is contradicted by “Let x be an element of the ring R” or, worse, where “x = 0” is later contradicted by “x ≠ 0” . Here’s more Functional Programming Doctrine:
As in mathematics, a function is a single-valued relation such that, given the same argument(s), it will return the same result. This is certainly not the case in the imperative programs.
Are functions single valued relations in mathematics? I guess, if we consider sets, vectors, and matrices and other collections to be single values. But given the same arguments, do they always return the same result? Not really: f(x) = mx+b depends on the parameters “m” and “b” as well as on the argument “x”. Consider the C function “f” defined by:
int f(int x){ static int b = 0; return x+ (b++); }
So ” x = f(1)+f(1)” is definitely not equal to “2*f(1)” (it is equal to 3 )*. You could look at this as: “C is a terrible construct of math illiterates who probably didn’t even know how to spell monod”, or you could see it as: parameter b changes between invocations of “f” . In fact, you could look at the original crime in FORTRAN where “x = 2” was introduced as a statement and think: this is a rational convention in response to both the absence of subscripts on teletype machines and the inability of computers to understand what “…” means in expressions like \(x_1 =2; x_{2} = x_1^2, …. x_n^n \) . Or consider a recursive function
\[ f(x) = \begin{cases}1 &\mbox{if }x\leq 0\\
x* f(x-1) &\mbox{otherwise}
\end{cases} \]
If we calculate this for \(f(2)\), we get \(x =2\) and then \(x = 1\) and then \(x = 0\). Which is it? The answer is that “x” takes on different values as the calculation changes state!
The differences between (a) axiomatic (declarative) definitions and (b) algorithmic definitions and (c) non-mathematical definitions, are not properly acknowledged in much of the functional programming literature. Calculations involve state change – of something. For most of the 20th century a “computer” was a person who calculated (computed). Like Katherine Johnson, Dorothy Vaughan, and Mary Jackson at NASA they carried out engineering and science (and cryptography) calculations before digital computers were widely available. Imagine such a human computer using Euler’s method. The “state of the computer” (the person doing the calculation) changes during the calculation as she iterates through (and possibly writes down intermediate results on paper). Similarly, electronic computers change state as they compute. Nothing to be afraid of here.
Not that the FP critique of imperative programming is all wrong. Functions that only modify their return value are often much easier to understand and validate and, too much programming still makes unstructured modifications to state – analogous to the old spaghetti code with unstructured control. New methods for clarifying what state can be changed by code sections and for facilitating modular decomposition of state would be useful. Fetishizing an axiomatic approach to function definition as “mathematical” seems less so.
See also Computer Science as a Scholarly discipline.
FOOTNOTES
* I hope.