Handout 0: Historical Development of “Programming” Concepts
Total Page:16
File Type:pdf, Size:1020Kb
06-02552 Princ. of Progr. Languages (and “Extended”) The University of Birmingham Spring Semester 2018-19 School of Computer Science c Uday Reddy2018-19 Handout 0: Historical development of “programming” concepts Digital computers were devised in the 1950’s and the activity of writing instructions for these computers came to be known as programming. However, “programming” in the broad sense of devising procedures, methods, recipes or rules for solving problems is much older, perhaps as old as humanity. As soon as human beings formed societies and started working together to carry out their daily activities, they needed to devise procedures for such activities and communicate them to each other, first in speech and then in writing. These ways of describing recipes are still in use pretty much the same way, and we use them in our daily lives, e.g., in following cooking recipes, using knitting patterns, or operating household gadgets. It is also in use in industrial and business contexts, e.g., for describing manufacturing processes on factory floor or business processes in organizations. “Programming” in mathematics is of special interest to us because it directly gave birth to programming in computer science. These programs are typically called algorithms, a term derived from the name of al-Khwarizmi, an Arab mathematician of 800 A.D., whose book Al-jabr wa’l muqabalah on algebraic manipulations was highly influential in the development of modern mathematics. The devising of mathematical algorithms began in pre-historic times as soon as numbers were invented to count and to measure. Methods were then needed for the arithmetic operations of addition, subtraction, multiplication, division and others. All these algorithms were devised in pre-historic times, even before civilization began, and we learn them in the early years of our schooling. Babylonian algorithms The earliest written description of an algorithm we have available is that for division, 1 more precisely for finding inverses x , found on a stone tablet dating back to the Sumerian civilization of Babylonia in 2000 B.C. The first few stanzas of the tablet read as follows:1 [The number is 4;10. What is its inverse? Proceed as follows. Form the inverse of 10, you will find 6. Multiply 6 by 4, you will find 24. Add on 1, you will find 25. Form the inverse of 25], you will find 2;24. [Multiply 2;24 by 6], you will find 14;24. [The inverse is 14;24]. Such is the way to proceed. [The number is 8;20]. What is its inverse? [Proceed as follows. Form the inverse of 20], you will find 3. Mul[tiply 3 by 8], you will find 24. [Add on 1], you will find [25]. [Form the inverse of 25], you will find 2;24. [Multiply 2;24 by 3L you will find [7;12. The inverse is 7;12. Such is the way to proceed]. Recall that the Babylonians used base 60 for their number system (whereas we use base 10). So, 4 and 10 are two separate digits in the base-60 number system, representing the number 4 × 60 + 10. The inverse of the number is 14; 24, i.e., 14 × 60−1 + 24 × 60−2. The details of the algorithm are not important for our purpose. But we should pay attention to the form of the algorithm. Notice the following facts: • Whereas, nowadays, we would use a symbol like x to denote the input of the algorithm, the Babylonians in 2000 B.C. did not yet have the symbolic notation. Instead, they described the algorithm on sample inputs, several of them in fact, to provide insight to the reader. 1Jean-Luc Chabert et al., A History of Algorithms: From the Pebble to the Microchip, Springer, 1994. 1 • Each step of the algorithm is an elementary operation such as addition or multiplication, which is described separately. From our point of view, this is like an assembly language where each elementary operation forms a separate instruction for the machine. • While the algorithm is described in an “imperative style,” i.e., expressed in terms of commands or instructions to the reader, the overall computation is functional. Each step of the algorithm acts on some inputs and produces some outputs, which then form the inputs for the succeeding steps. Mathematical algorithms are still described in this style, albeit intermixed with algebraic expressions. Euclid’s constructions Euclid, a Greek mathematician from Alexandria at around 300 B.C., wrote a treatise on mathematics called The Elements. It was divided into 13 “books” with books 1-4 devoted to plane geometry, books 5-10 to ratios and proportions, and books 11-13 to spatial geometry. Founded in geometry, Euclid’s Elements is full of geometric constructions that can be carried out with a ruler and compass. Such “constructions” are once again algorithms, imperative in style. But the imperative style in geometry has more significance than in algebr because, as the steps of a construction are carried out on paper or tablet, the figures on paper are modified with additional lines or arcs being drawn. Thus Euclid’s imperative constructions involve change of state of the figures on the paper. They do not merely produce “outputs.” Euclid’s constructions rarely ask one to erase the lines or arcs that have been drawn. However, many constructions do produce intermediate lines/arcs, which do not form part of the net result of the construction. All of these intermediate lines need to be erased at the end of the construction, a process similar to garbage collection in programming languages. Every construction of Euclid came with a specification, a precise statement of the problem being solved, and a proof of correctness to the effect that the construction solves the stated problem. Euclid was thus the founder of the rigorous method of mathematical proof, which has since become the standard in mathematics. Euclid might also be regarded as the founder of programming theory with rigorous specifications and proofs of correctness. But this latter aspect of his work has not yet been widely recognized.2 Diophantus and algebra Diophantus, another Greek mathematician from Alexandria in the third century A.D., took the decisive step of introducing algebraic notation for sequences of computation steps. Whereas the Babylonians wrote “multiply 6 by 4, you will find 24,” Diophantus introduced the short-hand notation familiar today: 6 ∗ 4. The advantage of the Diophantine notation is that one can string together multiple operations, all in a single expression. Thus sequential algorithms could now be written asp compact expressions or formulas. For example, a formula for a root of a quadratic equation is written as −b + b2 − 4ac. The development of computer programming languages paralleled the Diophantine invention, when scientists at IBM led by John Backus developed the programming language Fortran (short for “formula translation”). A computer program called a compiler was devised to translate Diophantine-style algebraic formulas into sequential algorithms in the machine language. Algebraic notation provides sequencing via function composition. When we write an expression such as g(f(x)), we are saying, “apply the function f to the value x obtaining an output, and then apply the function g to that output obtaining the final result.” Thus, the algebraic notation gives us a compact way of describing a long series of computation steps. However, sequencing alone is not enough to express all algorithms. One needs at least two other ingredients: conditional evaluation and repetition. Conditional evaluation is expressed in standard mathematics as definition by cases. For example: x; if x ≥ y max (x; y) = y; if x < y Similar notation is used in Haskell for definition by cases: max x y | x >= y = x | otherwise = y One also uses a simpler if-then-else form for conditional expressions: max (x; y) = if x ≥ y then x else y The introduction of repetition is however a much larger invention. 2I am indebted to Professor Tony Hoare for exhibiting these connections. 2 Peano, Godel¨ and primitive recursion Mathematicians have long used the principle called mathematical induction to prove statements parameterized by natural numbers. The so-called “natural numbers” are simply the series of non-negative integers 0; 1; 2;:::. The principle of mathematical induction is the following rule: A property P (n) is true for all natural numbers n provided: • Base case: P (0), i.e., P is true for 0, and • Step case: If P (x) is true for any natural number x, then it is true for P (x + 1). We can also express the principle as a proof rule as follows: P (0) 8x: P (x) ) P (x + 1) 8n: P (n) The key idea of the rule is that, in showing that P is true for x + 1, we can assume that it is already true for x. This assumption is referred to as the inductive hypothesis. The use of such inductive hypothesis is the key to proving properties indexed by an infinite collection of values such as that of natural numbers. For example, it is straightforward using mathematical induction to prove that the sum of the first n natural numbers can be given by a simple formula: n(n + 1) P (n) : 1 + 2 + ··· + n = 2 We leave the proof as an exercise. The essence of mathematical induction is problem reduction. The problem of the truth of P (x+1) is reduced to that of the truth of P (x), which I will display as: P (x + 1) P (x) This means, if you know how to prove P (x) then there is a way to prove P (x + 1). In this way the bigger problem of the truth of P (x + 1) is “reduced” to the smaller problem of the truth of P (x).