Lecture Notes for Com Sci 221, Programming Languages
Last modified: Fri Jan 27 15:13:25 1995
There are at least 4 different courses that are taught in different CS departments under the title of "Programming Languages":
So, in Com Sci 221, we will try to understand the fundamental structural issues that lead programming languages to be what they are. The course will not prepare you thoroughly to program in particular languages. But, it will give you the foundational insights to understand the programming languages of the future, when they are invented. It will not teach you to write interpreters and compilers, but it will prepare you to take a course, or read a book, on programming language implementation.
There are 3 different points of view from which to consider a programming language:
Once a programming language is designed and implemented, and in principle only the user needs to be involved with it, you might think that life becomes simpler. Not really. The problem is that users must do many things with programs. Introductory programming courses focus attention on writing programs, but that is only a small part of the activity involving a program, which includes:
Introductory programming courses, due to their limited time and resources, are inherently deceitful. Many instructors try to teach programming techniques that are appropriate for moderate sized (10s of pages) programs, heavily used by strangers over a long period of time, with a high cost for errors, a modest need for efficiency, and the potential for many modifications made in the future by strangers. This is a sensible choice, since it requires a very disciplined style of programming (it's easier to relax discipline in later work than to tighten it), but it can be done by individuals in a few days. And, fairly disciplined programming is advantageous in typical "real world" applications, where the cost of maintaining programs is much greater than the cost of writing them initially. Unfortunately, the actual experience you usually have with homework exercises is quite different. You write tiny programs (1 or 2 pages), use them once yourself to produce sample executions, feel no incentive for reliability, a slight incentive for efficiency, the programs are never modified, and you throw them away immediately after they are graded. Even in the "real world" it is hard to create incentives for disciplined programming, since the original creator of a program is often not the one who must maintain it.
Most students notice intuitively that the disciplined techniques espoused by the instructor are not really useful for just getting the assignments done. It is quite difficult to develop the vivid imagination required to see the utility of disciplined programming techniques in a more realistic setting than the completion of a homework assignment. Another hard thing about Com Sci 221 is that I require a lot of that sort of imagination. All of the homework programs will be really tiny examples, solving toy problems with only an oblique connection to the "real world." Rather than exercising programming ability, they will illustrate key structural concepts in the shortest possible way, by focussing on the special qualities that make one language essentially different from another. In spite of their tininess, the homework programs will be difficult because
Here is a simple thought experiment, intended only to open your mind to the fact that obvious facts about programs are often false.
Axiom: A correct program is better than an incorrect one.An axiom is a self-evident proposition, and it's hard to imagine anything much more self-evident than the proposition that a correct program is better than an incorrect one. Like many axioms, this one is false.
Consider the rather silly toy problem of printing out the vowels in the Roman alphabet (I'm already asking you to use your imagination to scale the structural qualities of tiny toy programs up to practical "real world" programs that would be too big to discuss in class). Here is a correct program to solve this problem, using Pascal notation:
Believe it or not, this program works. Now, consider the incorrect program:n := ord('A') for i := 4 to 8 do write(chr(n)) n := n + 2 * (i div 2)
Which is more valuable? (Remember, you are imagining that these programs are really much longer, so the work involved in writing them is substantial, rather than trivial.)write('A') write('E') write('O') write('U')
Although the first program is correct, it's hard to see why. If it were solving a problem for which you did not already know the answer (which is usually the case for useful programs), then it would be very difficult to develop confidence in the program. If an error were introduced by accident, it would be quite difficult to correct.
Although the second program is incorrect, it's obvious what it does, and very easy to correct the one small error. The resulting program is clear, and we can be pretty confident that it's now correct. Finally, imagine that we are told to reinterpret the problem so that 'Y' is also treated as a vowel. The second program is easy to modify for this purpose. It is hard to imagine modifying the first program for any reason.
In this course, we focus attention on the structure of programs and the languages that they are written in. What the heck is "structure"? Webster says:
For our purposes, the structure of a program is given by the operations that we can perform on the program, and the relation of the program to other objects of interest. For example, the relation of the program to its well-formed parts is clearly an important aspect of structure. But, the relation of a program to the other programs that it can be transformed into, and the amount of effort required for such transformations, are also crucial. In the second vowel-printing example above, the ease of transforming the program into a correct one is a key aspect of its structure. Also, the relation of a program to readable English text is a structural aspect that is important to clarity. Later in the course, when we study program typing, we will find that the relation of a correct program to similar syntactically incorrect programs may be important, and that the presence of the syntactically incorrect programs may even improve the structural properties of the correct one.
I have deliberately not attempted a precise definition of
program structure, but merely discussed its nature in a general
way. In effect, the interesting content of this course is the
discovery of which interpretations of the word "structure" are most
fruitful in various contexts. In a particular precisely defined
context, it is possible to give a precise definition of structure, but
we will never inhabit any single precisely defined context long enough
to make that worthwhile. If you are mathematically inclined, you might
wish to ponder the way in which algebra formalizes the
concept of structure (if not, you may ignore this passage with
impunity). The signature of a class of algebras determines
the operations and relations that are relevant in that
class. Isomorphism is structural equivalence, and
homomorphism shows that one structure is completely
represented by another.
End
Friday 6 January