This is my first rant about Computer Science topics because the programming language Pascal (by Niklaus Wirth) so offends me. I had been misinformed about its origins and had thought it not only a bad language but that its faults were totally unjustified. It seems that Niklaus started earlier than I had realised and could not have learned better from other efforts. Thus, Pascal is simply an example of how good intentions can yield poor results.
Here is a list of some of what I see as the failings, or negative teaching impacts, of the design decisions made:
- Pascal implementations were able to be made cheap (as in what it is worth) by specifying a one pass compiler. The compiler could not know (or even guess) what the type signature of a function was until it saw the declaration or definition. Thus, generations of programmer learned to write their programs upside down, defining a function before using it. Had the language simply required a declaration before the definition, there would have been no reward for upside down programs.
- The language provided for functions but not subroutines; the distinction being that functions were precluded from having an internal state that might affect the result returned. Real computing needs, unequivocally, subroutines. The trick to making a subroutine in Pascal is to have it depend on a variable that is outside the scope of the function. Students working with Pascal learn quickly to make all such stateful variables global, as the uses of such subroutines depend on them being in a scope higher than all uses. In the C programming language, such variables are declared in the routine, with the property “static”, and are thus hidden from all other code.
- Even as stateful variables were mistreated in functions, they were mishandled by the compiler. Generations of students learned to write active code to initalise the stateful variables. In the C programming language, such initialization is handled at compile and link-edit (“ld”) time.
- In the design of Pascal, clarity of intent was often sacrificed on the altar of programming purity. The earliest high level languages had found it very useful to be able to combine multiple tests of conditions into one statement, and Pascal followed suit. However, the rules for combining those tests were the exact opposite of what users really wanted. A very common combined test would abort a program run when the tests were to check that an index was high enough, that that same index was low enough, and that the member of an array at that index had a specific value. The user wanted to not check the member of the array if the index was out of bounds, but all parts of the combination had to be calculated. In the C programming language, such combinations were specified to be checked in order and the checking is to “short circuit” (skip the remaining tests) as soon as the result is sufficiently constrained (using logic identities like “true OR anything is true” and “false AND anything is false”).
- Pascal was supposed to protect programmers from bad practices, and to prevent programmers from circumventing the protections in it. This objective had far reaching impacts. In order to satisfy that requirement, the compiler needed to know all the intended linkages between every fragment of code that was to be combined into the final program. The two most common responses by implementors and users were to either require all the sources be available to compile any one fragment, or to require that there be only one complete file. Thus, a generation of students learned to build programs as one file. This made Pascal like BASIC, in that both were toys, unsuitable for large serious projects, as neither had standard mechanisms for partitioning up a large program.