A powerful programming language is more than just a means for instructing a computer to perform tasks. The language also serves as a framework within which we organize our ideas about processes. Thus, when we describe a language, we should pay particular attention to the means that the language provides for combining simple ideas to form more complex ideas. Every powerful language has three mechanisms for accomplishing this:
In programming, we deal with two kinds of elements:
functions
and
data. (Later we will discover that they are really not so distinct.)
Informally, data is stuff
that we want to manipulate, and
functions
are descriptions of the rules for manipulating the data.
Thus, any powerful programming language should be able to describe
primitive data and primitive
functions
and should have methods for
combining and abstracting
functions
and data.
In this chapter we will deal only with simple numerical data so that we can focus on the rules for building functions.[1] In later chapters we will see that these same rules allow us to build functions to manipulate compound data as well.
simple datais a barefaced bluff. In fact, the treatment of numbers is one of the trickiest and most confusing aspects of any programming language. Some typical issues involved are these: How large a number can we represent? How many decimal places of accuracy can we represent? Above and beyond these questions, of course, lies a collection of issues concerning roundoff and truncation errors—the entire science of numerical analysis. Since our focus in this book is on large-scale program design rather than on numerical techniques, we are going to ignore these problems. The numerical examples in this chapter will exhibit the usual roundoff behavior that one observes when using arithmetic operations that preserve a limited number of decimal places of accuracy in noninteger operations.