PRINCIPLES OF PROGRAMMING LANGUAGES: COURSE SPECIFICATION Gary T. Leavens Department of Computer Science, Iowa State University Ames, Iowa 50011-1040 USA leavens@cs.iastate.edu $Date: 1999/01/07 22:54:12 $ ABSTRACT Computer Science 342 studies the ideas behind major features of programming languages. To make these ideas clear and precise, it uses interpreters. This document specifies the course objectives. 1. INTRODUCTION Unlike courses that teach a specific programming language, Computer Science 342, ``Principles of Programming Languages,'' is a course about programming languages. The study of programming languages is primarily concerned with the following questions: * What are good ways to program? That is, what are expressive ways of specifying computational processes? * What are good ways to express programming idioms? * How does one precisely describe and implement the various features of programming languages? Com S 342 addresses all of these questions to some extent; as the course progresses, its emphasis shifts from the first questions above towards the last question. 1.1 COURSE DESCRIPTION The catalog description of Com S 342 at Iowa State University is as follows: Organization of programming languages emphasizing language design concepts and run time implementation. Study of major features of various programming languages. (3 credits). ``Organization'' means how the features of programming languages may be combined to form a unified whole. ``Language design concepts'' includes principles of good design (both technical and aesthetic), styles of programming (such as the functional, object-oriented, and declarative paradigms), the interactions among various features, and the costs of implementing various features. ``Run time implementation'' means the data structures and algorithms used to implement interpreters and compilers. A ``feature'' of a programming language is some piece of its syntax, together with the semantics (meaning) of that syntax. For example, an if-statement is a feature of Pascal, C, and BASIC. This offering of Com S 342 will focus on functional programming and major features of programming languages. The study of the functional paradigm, as a radically different way to program, helps show what features of programming languages are common to different paradigms, and highlights issues of organization and language design. The use of functional programming to describe interpreters is a primary technique used in the course. It helps to explain run time implementation techniques in a way that makes the semantics (meaning) of such features precise. Having an interpreter also allows one to experiment with such features and their variations. The features studied will be fundamental ones, such as scope and array models. The other topics will be touched on, including basic design concepts (such as regularity), but not high-level design principles such as parameter-declaration correspondence. 1.2 ACKNOWLEDGEMENTS My original ideas for this course at Iowa State were developed with the help of Kelvin Nilsen. Final exams for similar courses at other universities were provided by Kim Bruce (Williams College), Sam Kamin (University of Illinois), Dan Friedman and J. Michael Ashley (Indiana), and John Mitchell (Stanford); these helped provide perspective on what is important for such a course. I owe a great deal of thanks to Clyde Ruby, who was my TA and then an instructor for the course in its present form, and who provided much of the infrastructure for the course. 2. PREREQUISITES The formal prerequisites in the Iowa State catalog are successful completion of Com S 321, either Com S 309 or Com S 361, and credit or enrollment in Com S 331. 2.1 THEORY OF COMPUTING Com S 331 is a course in theory of computing. The main skill you need from Com S 331 is the ability to manipulate and work from context free grammars. For example, you should be able to write programs without parse errors using a context free (BNF) grammar for a programming language. In 342 we will extend and deepen your ability and familiarity with grammars. In language design, questions also arise as to what kinds of mistakes a language can check for; since many such questions are unsolvable, you will sometimes need to apply your knowledge of impossibility results (e.g., the halting problem). Computer Science 330 (discrete math) is a prerequisite to Com S 331. Several skills taught in Com S 330 are relevant to problem solving in general and to the kind of programming we will do in Com S 342. Familiarity with set theory, and recursive definitions is essential for various manipulations of syntax trees. Also needed are the concepts of the domain and range of a function, the ability to translate English into first-order predicate calculus (and set theory) and vice versa, and the ability to perform simple operations on logical expressions such as negation and simplification. These skills will help in type checking, in algebraic manipulation of programs, and in understanding formalized semantic ideas. 2.2 COMPUTER ORGANIZATION AND MACHINE LEVEL PROGRAMMING Com S 321 is an introductory course in computer architecture. The knowledge you need from Com S 321 includes an understanding of how data is represented in a computer, and assembly language programming. We will tap this knowledge in Com S 342 and expand on it to paint a more vivid picture of what happens in various programming languages at run time. 2.3 FILE ORGANIZATION AND PROCESSING OR SOFTWARE DEVELOPMENT PRACTICES Com S 361 is a course in file organization and processing. Com S 309 is a course in software development practices. From these courses you should have an appreciation for the problems of writing and maintaining medium-sized to large programs. You should also know how to design, modularize, and document a program. You should be thoroughly familiar with imperative programming techniques (assignment, looping, etc. as in C++, C, or Pascal). We will be studying imperative language features in 342. Com S 228 or a similar course is a prerequisite of Com S 361. From Com S 228 you should have a knowledge of the basics of object-based programming: abstract data types, classes, data and function members of classes. You should also have a working grasp of fundamental data structures: arrays, lists, stacks, queues, hashing, etc. We will draw on your grasp of fundamental data structures in building interpreters, and on your knowledge of object-based programming in studying object-oriented languages. We will expand on and deepen your knowledge of object-oriented concepts such as inheritance. 3. GENERAL OBJECTIVES The general objectives for Com S 342 are divided into two parts: a set of essential objectives, and a set of enrichment objectives. The essential objectives will be helpful for your career as a computer scientist; hence we want to help you to master them. You are encouraged to explore the enrichment objectives both for their own sake and because learning more about those will help deepen your understanding of the essential objectives. 3.1 ESSENTIAL OBJECTIVES In one sentence, the main objective is that you will have a deep, working knowledge of the functional paradigm and the key ideas used in modern programming languages. In more detail the essential objectives for Com S 342 are that you will be able to: * Write and modify programs using a mostly-functional style. This means programming that makes effective use of the abstraction mechanisms of functional languages, such as higher-order functions (functions that take functions as arguments and return functions as results) to achieve generality and abstraction. * Write and modify programs that make effective use of data abstraction. * Modify interpreters to change or enhance their behavior so as to implement various features of programming languages such as: control flow, variables, recursion, scoping, syntactic sugars, arrays, parameter passing mechanisms, objects, and inheritance. * Write programs using such features, and explain (using appropriate terminology) and answer questions about the user-visible behavior of such programs. * Explain (using appropriate terminology) and answer questions about the data structures and algorithms used in interpreters to implement such features. * Compare alternatives in the design and implementation of such features. You will be permitted to use the textbook and course notes for tasks involving programming, but not during tests. On tests you may be permitted a small amount of reference material. The functional style is one answer to the question: ``What are good ways to program?'' It also represents one major way to organize a programming language for parallel processing. Even if you do not become a programmer, the ideas of functional programming (function abstraction, referential transparency, etc.) have important applications in all areas of Computer Science (such as software specification, algorithm design, and of course in manipulation and specification of programming languages). These ideas also have application in many other contexts such as mathematics and engineering. Data abstraction is a key idea for allowing programs to be easily modifiable. It forms the basis for the object-oriented style of programming. One specific benefit of achieving these objectives is that your understanding will help you learn new languages quickly, by mapping key ideas and concepts from this class into the new language's syntax and semantics. For example, Java and other object-oriented languages (such as Smalltalk-80) use the ``indirect model'' of storage, which will be unfamiliar to you if you've programmed only in C++, C, Pascal, or Ada (all of which use the ``direct model''). We will study this model in detail, and you will gain practical programming experience with it, using Scheme. Learning this and other key ideas will also help you read (and write) a new language's reference manual. More importantly, understanding of fundamental concepts and run time implementation ideas will help you to better understand whatever language you program in; this will help you program more effectively. Being able to program better will also give you increased job satisfaction. 3.2 ENRICHMENT OBJECTIVES Enrichment objectives could be multiplied without limit, but the following seem most important or most easily taught using the course text. Following each of the enrichment objectives is a brief justification. * Design or critically evaluate design alternatives for languages and language features by careful consideration of their semantics. In designing software you will often be confronted with decisions about features that resemble those found in programming languages. This is particularly true for the design of user-interfaces and abstract data types. For example, a database management system has to deal with names for (say) relations, and thus must have scope rules; it will also have (difficult) type-checking problems, its query language will have control-flow issues, there will be demands for sweeter syntax, etc. The basic principles taught in this course can help with such design decisions, and can provide guidance for overall designs. Such skills are also important in judging whole languages, for example if you wish to buy a compiler for your PC, or if you become a manager of a group of programmers. * Be able to write the types of functions and use them in writing software. Types are an important way to summarize the behavior of functions, and a key way to check the basic sanity of software. Although types are best checked automatically by software tools, an understanding of them is important for writing such tools, and for aiding the quick construction of correct software. * Use algebraic techniques to modify, derive, and prove programs correct. Such techniques are a powerful aid in writing sophisticated programs and in reasoning about them. They represent the future of software engineering, which lies in design to specification (as opposed to debugging). * Explain and answer questions about the features found in widely-used programming languages, such as Pascal, C, C++, Ada, Java, BASIC, etc. This is a good way to deepen your understanding of such features. It also helps in informal or technical discussions. * Explain and answer questions about design principles such as regularity, the zero-one-many principle, orthogonality, etc. These principles form good rules-of-thumb that you can use in designing programs or languages. 4. CONVENTIONS FOR EVALUATION OF ANSWERS To ensure more objectivity in grading essay and programming questions, we establish the following conventions here. 4.1 SHORT ANSWERS AND ESSAYS Short answer questions will be graded on the basis of completeness (did you list all the relevant parts of the answer?) soundness (did you make any errors of fact or contradict yourself?) and clarity. You can help ensure clarity by giving examples where possible. For essays, critical justifications, and the like there may be no one right answer; so the criteria for judgement will be whether your essay are as follows. * clarity (you use examples where appropriate, you write clear sentences and diagrams, and you avoid excess verbosity), * soundness (you start from facts or reasonable assumptions, your logic is convincing), and * completeness (you consider relevant aspects of the problem and alternatives). The highest grade will be earned by an answer that is, in addition, concise and elegant; that is, answers that say the most with the least amount of excess. Extra consideration will be given to answers that are especially creative. 4.2 PROGRAM DIRECTIONS For programming problems, there is usually more than one right answer, hence it is important that your answer be clear and easy to understand. Answers to programming questions will be scored on the following points. * correctness (whether your program solves the given problem correctly in the given programming language). * elegance and clarity (conciseness, using relevant techniques to modularize the solution, making good use of language features). You should try to eliminate all syntax errors from your programs, as they will affect both the correctness and clarity of your solution; you may receive no points for programs with major syntax errors. Run-time space and time efficiency of programs is of secondary importance, unless the problem says otherwise. Checking of external inputs, prompting, labeling output, and other conventions for dealing with humans are not important (for this class), unless the problem says so. The breakdown of points between these categories is roughly as follows. * 70% for correctness (whether your program solves the given problem correctly in the given language). * 30\% for elegance and clarity (using relevant techniques to modularize the solution, making good use of language features). 5. TESTS Test questions will be similar to, but not the same as, the problems done for homework. The programming problems will only involve programming ideas that are discussed in class or in the text, perhaps from earlier chapters that we have covered. The specific ideas needed will not be stated, and to solve some problems two or more ideas may need to be combined. Problems may be stated by giving a specification and requiring that the entire solution be developed, or by giving a partial solution and requiring the completion of the unfinished parts of the solution. The specifications will be given using the terminology and techniques discussed in class, augmented with concrete examples. 6. DISCLAIMER The details of this course are subject to change as experience dictates. You will be informed of any changes.