Prologue: How to Program
When you were a small child, your parents taught you to count andConsider a quick look at On Teaching Part I. perform simple calculations with your fingers: “1 + 1 is 2”; “1 + 2 is 3”; and so on. Then they would ask “what’s 3 + 2?” and you would count off the fingers of one hand. They programmed, and you computed. And in some way, that’s really all there is to programming and computing.
Download DrRacket from its web site.
(+ 1 1)
The top half of DrRacket is called the definitions area. In this area, you create the programs, which is called editing. As soon as you add a word or change something in the definitions area, the SAVE button shows up in the top-left corner. When you click SAVE for the first time, DrRacket asks you for the name of a file so that it can store your program for good. Once your definitions area is associated with a file, clicking SAVE ensures that the content of the definitions area is stored safely in the file.
Programs consist of expressions. You have seen expressions in mathematics. For now, an expression is either a plain number or something that starts with a left parenthesis “(” and ends in a matching right parenthesis “)”—
which DrRacket rewards by shading the area between the pair of parentheses. - When you click RUN, DrRacket evaluates the expressions in the definitions area and shows their result in the interactions area. Then, DrRacket, your faithful servant, awaits your commands at the prompt (>). The appearance of the prompt signals that DrRacket is waiting for you to enter additional expressions, which it then evaluates like those in the definitions area:
> (+ 1 1) 2
Enter an expression at the prompt, hit the “return” or “enter” key on your keyboard, and watch how DrRacket responds with the result. You can do so as often as you wish:
Naturally, when DrRacket calculates for you, it uses the rules that you know
and love from math. Like you, it can determine the result of an addition
only when all the operands are plain numbers. If an operand is a
parenthesized operator expression—
> (+ (1) (2)) function call:expected a function after the open parenthesis, found a number
In this context, to program is to write down comprehensible arithmetic expressions, and to compute is to determine their value. With DrRacket, it is easy to explore this kind of programming and computing.
Arithmetic and Arithmetic
If programming were just about numbers and arithmetic, it would be as boring as mathematics. Fortunately, there is much more to programming than numbers: text, truths, images, and a great deal more.Just kidding: mathematics is a fascinating subject, but you won’t need much of it for now.
> "hello world" "hello world"
> (string-append "hello" "world") "helloworld"
> (string-append "hello " "world") "hello world"
(string-append "hello" " " "world")
You can do more with strings than append them. You can extract pieces from a string, reverse them, render all letters uppercase (or lowercase), strip blank spaces from the left and right, and so on. And best of all, you don’t have to memorize any of that. If you need to know what you can do with strings, look up the term in HelpDesk.Use F1 or the drop-down menu on the right to open HelpDesk. Look at the manuals for BSL and its section on pre-defined operations, especially those for strings.
> (+ (string-length "hello world") 20) 31
> (number->string 42) "42"
> (string->number "42") 42
> (string->number "hello world") #false
> (and #true #true) #true
> (and #true #false) #false
> (or #true #false) #true
> (or #false #false) #false
> (not #false) #true
(and (or (= (string-length "hello world") (string->number "11")) (string=? "hello world" "good morning")) (>= (+ (string-length "hello world") 60) 80))
>
Add (require 2htdp/image) to the definitions area, or select Add Teachpack from the Language menu and choose image from the Preinstalled HtDP/2e Teachpack menu.
(* (image-width ) (image-height ))
> (image-width (square 10 "solid" "red")) 10
> (image-width (overlay (rectangle 20 20 "solid" "blue") (circle 5 "solid" "red"))) 20
(place-image (circle 5 "solid" "green") 50 80 (empty-scene 100 100))
Let’s summarize again. To program is to write down an arithmetic
expression, but you’re no longer restricted to boring numbers. In BSL,
arithmetic is the arithmetic of numbers, strings, Booleans, and
even images. To compute, though, still means to determine the value of an
expression—
And now you’re ready to write programs that make rockets fly.
Inputs and Output
The programs you have written so far are pretty boring. You write down an expression or several expressions; you click RUN; you see some results. If you click RUN again, you see the exact same results. As a matter of fact, you can click RUN as often as you want, and the same results show up. In short, your programs really are like calculations on a pocket calculator, except that DrRacket calculates with all kinds of data, not just numbers.
That’s good news and bad news. It is good because programming and computing ought to be a natural generalization of using a calculator. It is bad because the purpose of programming is to deal with lots of data and to get lots of different results, with more or less the same calculations. (It should also compute these results quickly, at least faster than we can.) That is, you need to learn more still before you know how to program. No need to worry though: with all your knowledge about arithmetic of numbers, strings, Boolean values, and images, you’re almost ready to write a program that creates movies, not just some silly program for displaying “hello world” somewhere. And that’s what we’re going to do next.
Just in case you didn’t know, a movie is a sequence of images that are rapidly displayed in order. If your algebra teachers had known about the “arithmetic of images” that you saw in the preceding section, you could have produced movies in algebra instead of boring number sequences. Well, here is one more such table:
x =
1
2
3
4
5
6
7
8
9
10
y =
1
4
9
16
25
36
49
64
81
?
It turns out that making a movie is no more complicated than completing a table of numbers like that. Indeed, it is all about such tables:
x =
1
2
3
4
y =
y = the image that contains a dot x2 pixels below the top.
This second part means you must supply one number—
(y 1)
(y 2)
- First,
(define (FunctionName InputName) BodyExpression)
is a function definition. You recognize it as such because it starts with the “define” keyword. It essentially consists of three pieces: two names and an expression. The first name is the name of the function; you need it to apply the function as often as you wish. The second name—called a parameter— represents the input of the function, which is unknown until you apply the function. The expression, dubbed body, computes the output of the function for a specific input. - Second,
(FunctionName ArgumentExpression)
is a function application. The first part tells DrRacket which function you wish to use. The second part is the input to which you want to apply the function. If you were reading a Windows or a Mac manual, it might tell you that this expression “launches” the “application” called FunctionName and that it is going to process ArgumentExpression as the input. Like all expressions, the latter is possibly a plain piece of data or a deeply nested expression.
> (empty-scene 100 60)
> (place-image 50 23 (empty-scene 100 60))
> (place-image 50 20 (empty-scene 100 60)) > (place-image 50 30 (empty-scene 100 60)) > (place-image 50 40 (empty-scene 100 60))
(define (picture-of-rocket height) (place-image 50 height (empty-scene 100 60)))
(picture-of-rocket 0) (picture-of-rocket 10) (picture-of-rocket 20) (picture-of-rocket 30)
Add (require 2htdp/universe) to the definitions area, or select Add Teachpack from the Language menu and choose universe from the Preinstalled HtDP/2e Teachpack menu.
> (animate picture-of-rocket)
As soon as you hit the “return” key, DrRacket evaluates the expression; but
it does not display a result, not even a prompt. It opens
another window—
So here is what you learned in this section. Functions are useful because they can process lots of data in a short time. You can launch a function by hand on a few select inputs to ensure that it produces the proper outputs. This is called testing a function. Or, DrRacket can launch a function on lots of inputs with the help of some teachpacks; when you do that, you are running the function. Naturally, DrRacket can launch functions when you press a key on your keyboard or when you manipulate the mouse of your computer. To find out how, keep reading. Whatever triggers a function application isn’t important, but do keep in mind that (simple) programs are functions.
Many Ways to Compute
When you evaluate (animate picture-of-rocket), the rocket eventually disappears into the ground. As Venkat Pamulapati notes, SpaceX has landed many rockets vertically since these words were written. That’s plain silly. Rockets in old science fiction movies don’t sink into the ground; they gracefully land on their bottoms, and the movie should end right there.
This idea suggests that computations should proceed differently, depending on the situation. In our example, the picture-of-rocket program should work “as is” while the rocket is in flight. When the rocket’s bottom touches the bottom of the canvas, however, it should stop the rocket from descending any farther.
In a sense, the idea shouldn’t be new to you. Even your mathematics teachers define functions that distinguish various situations:
> (sign 10) 1
> (sign -5) -1
> (sign 0) 0
This is a good time to explore what the STEP button does. Add (sign -5) to the definitions area and click STEP for the above sign program. When the new window comes up, click the right and left arrows there.
(cond [ConditionExpression1 ResultExpression1] [ConditionExpression2 ResultExpression2] ... [ConditionExpressionN ResultExpressionN])
(define (picture-of-rocket.v2 height) (cond [(<= height 60) (place-image 50 height (empty-scene 100 60))] [(> height 60) (place-image 50 60 (empty-scene 100 60))]))
With this knowledge, you can now change the course of the simulation. The goal is to not let the rocket descend below the ground level of a 100-by-60 scene. Since the picture-of-rocket function consumes the height where it should place the rocket in the scene, a simple test comparing the given height to the maximum height appears to suffice.
See figure 5 for the revised function definition. The definition uses the name picture-of-rocket.v2 to distinguish the two versions. Using distinct names also allows us to use both functions in the interactions area and to compare the results. Here is how the original version works:
> (picture-of-rocket 5555)
> (picture-of-rocket.v2 5555)
> (animate picture-of-rocket.v2)
Stop! What do you think we want to see?
Landing the rocket this far down is ugly. Then again, you know how to fix this aspect of the program. As you have seen, BSL knows an arithmetic of images. When place-image adds an image to a scene, it uses its center point as if it were the whole image, even though the image has a real height and a real width. As you may recall, you can measure the height of an image with the operation image-height. This function comes in handy here because you really want to fly the rocket only until its bottom touches the ground.
(- 60 (/ (image-height ) 2))
(place-image 50 (- 60 (image-height )) (empty-scene 100 60))
(- 60 (/ (image-height ) 2))
(define (picture-of-rocket.v3 height) (cond [(<= height (- 60 (/ (image-height ) 2))) (place-image 50 height (empty-scene 100 60))] [(> height (- 60 (/ (image-height ) 2))) (place-image 50 (- 60 (/ (image-height ) 2)) (empty-scene 100 60))]))
When you think and experiment along these lines, you eventually get to the program in figure 6. Given some number, which represents the height of the rocket, it first tests whether the rocket’s bottom is above the ground. If it is, it places the rocket into the scene as before. If it isn’t, it places the rocket’s image so that its bottom touches the ground.
One Program, Many Definitions
Now suppose your friends watch the animation but don’t like the size of
your canvas. They might request a version that uses
200-by-400 scenes. This simple request forces you to
replace 100 with 400 in five places in the program and
60 with 200 in two other places—
Stop! Before you read on, try to do just that so that you get an idea of how difficult it is to execute this request for a five-line program. As you read on, keep in mind that programs in the world consist of 50,000 or 500,000 or even 5,000,000 or more lines of program code.
(define Name Expression)
(define HEIGHT 60)
(define (picture-of-rocket.v4 h) (cond [(<= h (- HEIGHT (/ (image-height ROCKET) 2))) (place-image ROCKET 50 h (empty-scene WIDTH HEIGHT))] [(> h (- HEIGHT (/ (image-height ROCKET) 2))) (place-image ROCKET 50 (- HEIGHT (/ (image-height ROCKET) 2)) (empty-scene WIDTH HEIGHT))])) (define WIDTH 100) (define HEIGHT 60) (define ROCKET )
> (animate picture-of-rocket.v4)
The program in figure 7 consists of four definitions: one
function definition and three constant definitions. The numbers
100 and 60 occur only twice—
When DrRacket evaluates (animate picture-of-rocket.v4), it replaces HEIGHT with 60, WIDTH with 100, and ROCKET with the image every time it encounters these names. To experience the joys of real programmers, change the 60 next to HEIGHT into a 400 and click RUN. You see a rocket descending and landing in a 100 by 400 scene. One small change did it all.
(- HEIGHT (/ (image-height ROCKET) 2))
(define ROCKET-CENTER-TO-TOP (- HEIGHT (/ (image-height ROCKET) 2)))
While the order of constant definitions matters, it does not matter where you place constant definitions relative to function definitions. Indeed, if your program consists of many function definitions, their order doesn’t matter either, though it is good to introduce all constant definitions first, followed by the definitions of functions in decreasing order of importance. When you start writing your own multi-definition programs, you will see why this ordering matters.
; constants (define WIDTH 100) (define HEIGHT 60) (define MTSCN (empty-scene WIDTH HEIGHT)) (define ROCKET ) (define ROCKET-CENTER-TO-TOP (- HEIGHT (/ (image-height ROCKET) 2))) ; functions (define (picture-of-rocket.v5 h) (cond [(<= h ROCKET-CENTER-TO-TOP) (place-image ROCKET 50 h MTSCN)] [(> h ROCKET-CENTER-TO-TOP) (place-image ROCKET 50 ROCKET-CENTER-TO-TOP MTSCN)]))
The program also contains two line comments, introduced with semicolons (“;”). While DrRacket ignores such comments, people who read programs should not because comments are intended for human readers. It is a “back channel” of communication between the author of the program and all of its future readers to convey information about the program.
Once you eliminate all repeated expressions, you get the program in figure 8. It consists of one function definition and five constant definitions. Beyond the placement of the rocket’s center, these constant definitions also factor out the image itself as well as the creation of the empty scene.
How would you change the program to create a 200-by-400 scene?
How would you change the program so that it depicts the landing of a green UFO (unidentified flying object)? Drawing the UFO is easy:
(overlay (circle 10 "solid" "green") (rectangle 40 4 "solid" "green")) How would you change the program so that the background is always blue?
How would you change the program so that the rocket lands on a flat rock bed that is 10 pixels higher than the bottom of the scene? Don’t forget to change the scenery, too.
Magic Numbers Take another look at picture-of-rocket.v5. Because we eliminated all repeated expressions, all but one number disappeared from this function definition. In the world of programming, these numbers are called magic numbers, and nobody likes them. Before you know it, you forget what role the number plays and what changes are legitimate. It is best to name such numbers in a definition.
Here we actually know that 50 is our choice for an x-coordinate for the rocket. Even though 50 doesn’t look like much of an expression, it really is a repeated expression, too. Thus, we have two reasons to eliminate 50 from the function definition, and we leave it to you to do so.
One More Definition
(define (picture-of-rocket t) (cond [(<= t ROCKET-CENTER-TO-TOP) (place-image ROCKET 50 t MTSCN)] [(> t ROCKET-CENTER-TO-TOP) (place-image ROCKET 50 ROCKET-CENTER-TO-TOP MTSCN)]))
Even if you have never taken a physics course, you know that a time is not a distance. So somehow our program worked by accident. Don’t worry, though; it is all easy to fix. All you need to know is a bit of rocket science, which people like us call physics.
You might wonder why V is 3 here. There is no special reason. We consider 3 pixels per clock tick a good velocity. You may not. Play with this number and see what happens with the animation.
; properties of the "world" and the descending rocket (define WIDTH 100) (define HEIGHT 60) (define V 3) (define X 50) ; graphical constants (define MTSCN (empty-scene WIDTH HEIGHT)) (define ROCKET ) (define ROCKET-CENTER-TO-TOP (- HEIGHT (/ (image-height ROCKET) 2))) ; functions (define (picture-of-rocket.v6 t) (cond [(<= (distance t) ROCKET-CENTER-TO-TOP) (place-image ROCKET X (distance t) MTSCN)] [(> (distance t) ROCKET-CENTER-TO-TOP) (place-image ROCKET X ROCKET-CENTER-TO-TOP MTSCN)])) (define (distance t) (* V t))
> (animate picture-of-rocket.v6)
In comparison to the previous versions of picture-of-rocket,
this one shows that a program may consist of several function definitions
that refer to each other. Then again, even the first version used
+ and /—
As you become a true-blue programmer, you will find out that programs
consist of many function definitions and many constant definitions. You
will also see that functions refer to each other all the time. What you
really need to practice is to organize them so that you can read them
easily, even months after completion. After all, an older version of
you—
You Are a Programmer Now
The claim that you are a programmer may have come as a surprise to you at the end of the preceding section, but it is true. You know all the mechanics that there are to know about BSL. You know that programming uses the arithmetic of numbers, strings, images, and whatever other data your chosen programming languages support. You know that programs consist of function and constant definitions. You know, because we have told you, that in the end, it’s all about organizing these definitions properly. Last but not least, you know that DrRacket and the teachpacks support lots of other functions and that DrRacket’s HelpDesk explains what these functions do.
You might think that you still don’t know enough to write programs that react to keystrokes, mouse clicks, and so on. As it turns out, you do. In addition to the animate function, the 2htdp/universe teachpack provides other functions that hook up your programs to the keyboard, the mouse, the clock, and other moving parts in your computer. Indeed, it even supports writing programs that connect your computer with anybody else’s computer around the world. So this isn’t really a problem.
In short, you have seen almost all the mechanics of putting together programs. If you read up on all the functions that are available, you can write programs that play interesting computer games, run simulations, or keep track of business accounts. The question is whether this really means you are a programmer. Are you?
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Not!
When you look at the “programming” bookshelves in a random bookstore, you will see loads of books that promise to turn you into a programmer on the spot. Now that you have worked your way through some first examples, however, you probably realize that this cannot possibly happen.
Acquiring the mechanical skills of programming—
Good programming is far more than the mechanics of acquiring a
language. Most importantly, it is about keeping in mind that programmers
create programs for other people to read them in the future. A good
program reflects the problem statements and its important concepts. It
comes with a concise self-description. Examples illustrate this
description and relate it back to the problem. The examples make sure that
the future reader knows why and how your code works. In short, good
programming is about solving problems systematically and conveying the
system within the code. Best of all, this approach to programming actually
makes programming accessible to everyone—
The rest of this book is all about these things; very little of the book’s content is actually about the mechanics of DrRacket, BSL, or teachpacks. The book shows you how good programmers think about problems. And, you will even learn that this way of solving problems applies to other situations in life, such as the work of doctors, journalists, lawyers, and engineers.
Oh, and by the way, the rest of the book uses a tone that is more appropriate for a serious text than this Prologue. Enjoy!
Note on What This Book Is Not About Introductory books on programming tend to contain lots of material about the authors’ favorite application discipline: puzzles, mathematics, physics, music, and so on. Such material is natural because programming is obviously useful in all these areas, but it also distracts from the essential elements of programming. Hence, we have made every attempt to minimize the use of knowledge from other areas so that we can focus on what computer science can teach you about computational problem solving.