On this page:
Arithmetic And Arithmetic
Inputs And Output
Many Ways To Compute
One Program, Many Definitions
One More Definition
You Are a Programmer Now
Not!

Prologue: How to Program

When you were a small child, your parents probably taught you to count and later to 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.

Start DrRacket and choose “Beginning Student Language” from the “How to Design Programs” submenu in the “Language” menu.

Now you’re switching roles. You program, and the computer is a child. Of course, you start with the simplest of all calculations. You type

(+ 1 1)

into the top part of DrRacket, click RUN, and a result shows up in the bottom part: 2

That’s how simple programming is. You ask questions as if DrRacket were a child, and DrRacket computes for you. People often say the “computer does X for you” but in reality, a plain computer is pretty useless. It is software that computes. You can also ask DrRacket to process several requests at once:
(+ 2 2)
(* 3 3)
(- 4 2)
(/ 6 2)
After you click RUN, you see 4 9 2 3 in the bottom half of DrRacket, which are the expected results.

Terminology At this point, we slow down for a moment and introduce some terms:
  • 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:
    > (+ 2 2)

    4

    > (* 3 3)

    9

    > (- 4 2)

    2

    > (/ 6 2)

    3

    > (sqr 3)

    9

    > (expt 2 3)

    8

    > (sin 0)

    0

    > (cos pi)

    #i-1.0

Take a close look at the last number. Its “#i” prefix is short for “I don’t really know the precise number so take that for now” or inexact number. Unlike your calculator or most other programming systems, DrRacket is extremely honest. When it doesn’t know the exact number, it warns you with this special prefix. Later, we shall show you really strange facts about “computer numbers,” and you will then truly appreciate that DrRacket issues such warnings.

Enough terminology for now.

By now, you might be wondering whether DrRacket can add more than two numbers at once, and yes, it can! As a matter of fact, it can do it in two different ways:
> (+ 2 (+ 3 4))

9

> (+ 2 3 4)

9

The first one is nested arithmetic, as you know it from school. The second one is Racket arithmetic and it is natural, if you always use parentheses to group operations and numbers together. This is as a good a time as any to discuss the nature of our notation—dubbed Beginning Student Language or just BSLsomething you might have pondered for a while now.

This book does not teach you Racket, even if the software is called DrRacket. Instead it uses a series of teaching languages created for learning design principles. Once you have mastered these languages, you can quickly learn to program in all kinds of programming languages, including Racket and also JavaScript, Python, Ruby, and others.

In BSL, every time you want to use a “calculator operation,” you write down an opening parenthesis followed by the operation, the numbers on which the operation should work (separated by spaces or even line breaks), and ended by a closing parenthesis. The items following the operation are called the operands. Nested arithmetic means that you can use an expression for an operand, which is why
> (+ 2 (+ 3 4))

9

is a fine program. You can do this as often as you wish:
> (+ 2 (+ (* 3 3) 4))

15

> (+ 2 (+ (* 3 (/ 12 4)) 4))

15

> (+ (* 5 5) (+ (* 3 (/ 12 4)) 4))

38

There are no limits to nesting, except for your patience.

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—something that starts with a “(” and an operation—it determines the result of that nested expression first. Unlike you, it never needs to ponder which expression to calculate first—because this first rule is the only rule there is to it.

The price for DrRacket’s convenience is that parentheses have meaning. You, the programmer, must enter all these parentheses, and you may not enter too many. For example, while extra parentheses are acceptable to your math teacher, this is not the case for BSL. The expression (+ (1) (2)) contains way too many parentheses, and DrRacket lets you know in no uncertain terms:
> (+ (1) (2))

function call: expected a function after the open parenthesis, but found a number

Once you get used to BSL programming though, you will see that it isn’t a price at all. First, you get to use operations on several operands at once, if it is natural to do so:Or you place the cursor next to the operation and hit F1. This action opens DrRacket’s HelpDesk and searches for the documentation of the operation. Use the results concerning the HtDP teaching languages. As you may have noticed by now, this text is also linked to the documentation in HelpDesk.
> (+ 1 2 3 4 5 6 7 8 9 0)

45

> (* 1 2 3 4 5 6 7 8 9 0)

0

If you don’t know what an operation does for several operands, enter an example into the interactions area and hit "return"; DrRacket lets you know whether and how it works. Second, when you will read programs that others write—which you will do for about half the time of your programmer life—you will never have to wonder which expressions are evaluated first. The parentheses and the nesting will immediately tell you so.

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.Just kidding: mathematics is a fascinating subject, but you knew that. You won’t need too much of it for now, though if you want to be a really great programmer, you will need to study some. Fortunately, there is much more to programming than numbers: text, truths, images, and more.

Here are three programs that deal with text:
(string-append "hello" "world")
(string-append "hello " "world")
(string-append "hell" "o world")
After you click RUN, DrRacket displays three results: "helloworld" "hello world" "hello world"

To understand exactly what’s going on, you first need to know that in BSL, text is any sequence of keyboard characters enclosed in double-quotes ("). Technically, this is called a string. Thus, "hello world", is a perfectly fine string and, when DrRacket evaluates this string, it displays it in the interactions area, just like a number. Indeed, many people’s first program is one that displays the words “hello” and “world”—you wrote three of them already but the simplest one is to type in the string by itself:

"hello world"

Click RUN and admire the output of the program.

Otherwise, you need to know that in addition to an arithmetic of numbers, DrRacket also knows about an arithmetic of strings. Thus, string-append is an operation just like +; it makes a string by adding the second to the end of the first. As the first line shows, it does this literally, without adding anything between the two strings: no blank space, no comma, nothing. Thus, if you want to see the phrase "hello world", you really need to add a space to one of these words somewhere; that’s what the second and third line show. Of course, the most natural way to create this phrase from the two words is to enter

(string-append "hello" " " "world")

because string-append, like +, can deal with as many operands as you wish.

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 blanks 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 it up in HelpDesk. Use F1 or the drop-down menu on the right to open HelpDesk, look at the manuals for HtDP languages (BSL) and its section on primitives. It lists all the operations in BSL and especially those that work on strings.

If you did look up the primitive operations of BSL, you saw that primitive (also called built-in) operations can consume strings and produce numbers. You therefore can, if you so desire, add the length of a string to 20:
> (+ (string-length "hello world") 20)

31

and DrRacket evaluates this expressions like any other one. That is, an arithmetic operation doesn’t have to be about just numbers or just strings. Many of them mix and match as needed. And then there are operations that convert strings into numbers and numbers into strings and you get what you expect:
> (number->string 42)

"42"

> (string->number "42")

42

If you expected “forty-two” or something clever along those lines, sorry, that’s really not what you want from a string calculator.

The second expression raises a question, though. What if string->number isn’t used with a string that is a number wrapped in string quotes? In that case the operation produces a totally different kind of result:
> (string->number "hello world")

false

This is neither a number nor a string; it is a Boolean. Unlike numbers and strings, Boolean values come in only two varieties: true and false. The first is truth, the second falsehood. Even so, DrRacket has several operations for combining Boolean values:
> (and true true)

true

> (and true false)

false

> (or true false)

true

> (or false false)

false

> (not false)

true

and you get the results that the name of the operation suggests. (Don’t know what and, or, and not compute? Easy: (and x y) is true if x and y are true; (or x y) is true if either x or y or both are true; and (not x) results in true precisely when x is false.)

Although it isn’t possible to convert one number into a Boolean, it is certainly useful to “convert” two numbers into a Boolean:
(> 10 9)
(< -1 0)
(= 42 9)
Guess what the results are before you move on:

true

true

false

Now try these: (>= 10 10), (<= -1 0), and (string=? "design" "tinker"). This last one is totally different again but don’t worry, you can do it.

With all these new kinds of data—yes, numbers, strings, and Boolean values are data—and operations floating around, it is easy to forget some basics, like nested arithmetic:
(and (or (= (string-length "hello world") (string->number "11"))
         (string=? "hello world" "good morning"))
     (>= (+ (string-length "hello world") 60) 80))
What is the result of this expression? How did you figure it out? All by yourself? Or did you just type it into DrRacket’s interactions area and hit the "return" key? If you did the latter, do you think you would know how to do this on your own? After all, if you can’t predict what DrRacket does for small expressions, you may not want to trust it when you submit larger tasks than that for evaluation.

Before we show you how to do some “real” programming, let’s discuss one more kind of data to spice things up: images. To insert images such as this rocket into DrRacket, use the Insert menu and select the “Insert image ...” item. Or, if you’re reading this book on-line, copy-and-paste the image from your browser into DrRacket. When you insert an image into the interactions area and hit return like this

> 

DrRacket replies with the image. In contrast to many other programming languages, BSL understands images, and it supports an arithmetic of images just as it supports an arithmetic of numbers or strings. In short, your programs can calculate with images, and you can do so in the interactions area. Furthermore BSL programmers—like the programmers for other programming languages—create libraries that others may find helpful. Using such libraries is just like expanding your vocabularies with new words or your programming vocabulary with new primitives. We call such libraries teachpacks because they are helpful with teaching.

(require 2htdp/image) specifies that you wish to add the "image" library. Alternatively, use the “Language” drop-down menu, choose “Add Teachpack ...” and pick "image". One important library—"image"supports operations for computing the width and height of an image:
(* (image-width )
   (image-height ))
Once you have added a library to your program, clicking RUN gives you 1176 because that’s the area of a 28 by 42 image.

You don’t have to use Google to find images and insert them in your DrRacket programs with the “Insert” menu. You can also instruct DrRacket to create simple images from scratch:
> (circle 10 "solid" "red")

image

> (rectangle 30 20 "outline" "blue")

image

Best of all, DrRacket doesn’t just draw images, because it really considers them values just like numbers. So naturally BSL has operations for combining images just like it has operations for adding numbers or appending strings:
> (overlay (circle 5 "solid" "red")
           (rectangle 20 20 "solid" "blue"))

image

Overlaying the same images in the opposite order produces a solid blue square:
> (overlay (rectangle 20 20 "solid" "blue")
           (circle 5 "solid" "red"))

image

Stop and reflect on this last result for a moment.

As you can see overlay is more like string-append than +, but it does “add” images just like string-append “adds” strings and + adds numbers. Here is another illustration of the idea:
> (image-width (square 10 "solid" "red"))

10

> (image-width
    (overlay (rectangle 20 20 "solid" "blue")
             (circle 5 "solid" "red")))

20

These interactions with DrRacket don’t draw anything at all; they really just measure their width.

You should know about two more operations: empty-scene and place-image. The first creates a scene, a special kind of rectangle. The second places an image into such a scene:
(place-image (circle 5 "solid" "green")
             50 80
             (empty-scene 100 100))
and you get this: Not quite. The image comes without a grid. We superimpose the grid on the empty scene so that you can see where exactly the green dot is placed.

As you can see from this image, the origin (or (0,0)) is in the upper-left corner. Unlike in mathematics, the y coordinate is measured downwards, not upwards. Otherwise, the image shows what you should have expected: a solid green disk at the coordinates (50,80) in a 100 by 100 empty rectangle.

Let’s summarize again. To program is to write down an arithmetic expression, but you’re no longer restricted to boring numbers. With BSL, your arithmetic is the arithmetic of numbers, strings, Boolean values, and even images. To compute though still means to determine the value of the expressions(s) except that this value can be a string, a number, a Boolean, or an image.

And now you’re basically 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. Remember those tables that your teachers would show you? Here is one more:

x =

1

2

3

4

5

6

7

8

9

10

y =

1

4

9

16

25

36

49

64

81

?

Your teachers would now ask you to fill in the blank, i.e., replace the “?” mark with a number.

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

5

6

y =

?

To be concrete, your teacher should ask you here to draw the sixth image, the seventh, and the 1273rd one because a movie is just a lot of images, some 20 or 30 of them per second. So you need some 1200 to 1800 of them to make one minute’s worth of it.

You may also recall that your teacher not only asked for the fifth, sixth, or seventh number in some sequence but also for an expression that determines any element of the sequence from a given x. In the numeric example, the teacher wants to see something like this:Write x2 if you want to be fancy.

If you plug in 1, 2, 3, and so on for x, you get 1, 4, 9, and so on for yjust as the table says. For the sequence of images, you could say something like

y = the image that contains a dot x2 pixels below the top.

The key is that these one-liners are not just expressions but functions.

At first glance functions are like expressions, always with a y on the left, followed by an = sign, and an expression. They aren’t expressions, however. And the notation you (usually) learn in school for functions is utterly misleading. In DrRacket, you therefore write functions a bit differently:

(define (y x) (* x x))

The define says “consider y a function”, which like an expression, computes a value. A function’s value, though, depends on the value of something called the input, which we express with (y x). Since we don’t know what this input is, we use a name to represent the input. Following the mathematical tradition, we use x here to stand in for the unknown input but pretty soon, we shall use all kinds of names.

This second part means you must supply one value—a number—for x to determine a specific value for y. When you do, DrRacket plugs in the value for x into the expression associated with the function. Here the expression is (* x x). Once x is replaced with a value, say 1, DrRacket can compute the result of the expressions, which is also called the output of the function.

Click RUN and watch nothing happen. Nothing shows up in the interactions area. Nothing seems to change anywhere else in DrRacket. It is as if you hadn’t accomplished anything. But you did. You actually defined a function and informed DrRacket about its existence. As a matter of fact, the latter is now ready for you to use the function. Enter

(y 1)

at the prompt in the interactions area and watch a 1 appear in response. The (y 1) is called a function application in DrRacket.... and in mathematics, too. Your teachers just forgot to tell you. Try

(y 2)

and see a 4 pop out. Of course, you can also enter all these expressions in the definitions area and click RUN:
(define (y x) (* x x))
 
(y 1)
(y 2)
(y 3)
(y 4)
(y 5)
In response, DrRacket displays: 1 4 9 16 25, which are the numbers from the table. Now determine the missing entry.

What all this means for you is that functions provide a rather economic way of computing lots of interesting values with a single expression. Indeed, programs are functions, and once you understand functions well, you know almost everything there is about programming. Given their importance, let’s recap what we know about functions so far:
  • First,

    (define (FunctionName InputName) BodyExpression)

    is a function definition. You recognize it as such, because it starts with the “define” keyword. A function definition 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—most programmers call it a parameterrepresents 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. As seen, the expression involves the parameter, and it may also consist of many other expressions.

  • 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 wish to apply the function. If you were reading a Windows or Mac manual, it might tell you that this expression “launches” the (software) “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 (number, string, image, Boolean) or a complex, deeply nested expression.

Functions can input more than numbers, and they can output all kinds of data, too. Our next task is to create a function that simulates the second table—the one with images of a gray dot—just like the first function simulated the numeric table. Since the creation of images from expressions isn’t something you know from high school, let’s start simply. Do you remember empty-scene? We quickly mentioned it at the end of the previous section. When you type it into the definitions area, like that:

(empty-scene 100 100)

clicking RUN produces an empty rectangle, also called a scene:

You can add images to a scene with place-image:

(place-image  50 0 (empty-scene 100 100))

produces an scene with a rocket hovering near the center of the top:

Think of the rocket as an object that is like the disk—though more interesting—in the above table from your mathematics class.

Next you should make the rocket descend, just like the disk in the above table. From the preceding section you know how to achieve this effect by increasing the y coordinate that is supplied to place-image:
(place-image  50 10 (empty-scene 100 100))
(place-image  50 20 (empty-scene 100 100))
(place-image  50 30 (empty-scene 100 100))
Clicking RUN yields three scenes:

All that’s needed now is to produce lots of these scenes easily and to display all of them in rapid order.

The first goal can be achieved with a function of course:
(define (create-rocket-scene height)
  (place-image  50 height (empty-scene 100 100)))
Yes, this is a function definition. Instead of y, it uses the name create-rocket-scene, a name that immediately tells you what the function outputs: a scene with a rocket. Instead of x, the function definition uses height for the name of its parameter, a name that suggests that it is a number and that it tells the function where to place the rocket. The body expression of the function is just like the series of expressions with which we just experimented, except that it uses height in place of a number. And we can easily create all of those images with this one function:
(create-rocket-scene 0)
(create-rocket-scene 10)
(create-rocket-scene 20)
(create-rocket-scene 30)
Try this out in the definitions area or the interactions area, both create the expected scenes.

(require 2htdp/universe) The second goal requires knowledge about one additional primitive operation from the "universe" library: animate. So, add the require line to the definitions area, click RUN, and enter the following expression:

> (animate create-rocket-scene)

Stop for a moment and note that the argument expression is a function. Don’t worry for now about using functions as arguments; it works well with animate but don’t try this at home yet.

As soon as you hit the “return” key, DrRacket evaluates the expression but it does not display a result, not even an interactions prompt (for a while). It open another window—a canvasand starts a clock that ticks 28 times per second. Every time the clock ticks, DrRacket applies create-rocket-scene to the number of ticks passed since this function call. The results of these function calls are displayed in the canvas, and it produces the effect of an animated movie. The simulation runs until you click STOP or close the window. At that point, animate returns the number of ticks that have passed.

The question is where the images on the window come from. The short explanation is that animate runs its operand on the numbers 0, 1, 2, etc. and displays the resulting images. The long explanation is this:
  • animate starts a clock, and animate counts the number of clock ticks;

  • the clock ticks 28 times per second;

  • every time the clock ticks, animate applies the function create-rocket-scene to the current clock tick; and

  • the scene that this application creates is displayed on the screen.

This means that the rocket first appears at height 1, then 2, then 3, etc., which explains why the rocket descends from the top of the screen to the bottom. That is, our three-line program creates some 100 pictures in about 3.5 seconds, and displaying these pictures rapidly creates the effect of a rocket descending to the ground.

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 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 libraries; 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 just functions.

Many Ways To Compute

When you run the create-rocket-scene program from the preceding section, the rocket eventually disappears in the ground. 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 create-rocket-scene program should work “as is” while the rocket is in-flight. When the rocket’s bottom touches the bottom of the screen, however, it should stop the rocket from descending any further.

In a sense, the idea shouldn’t be new to you. Even your mathematics teachers define functions that distinguish various situations:

This sign distinguishes three kinds of inputs: those numbers larger than 0, those equal to 0, and those smaller than 0. Depending on the input, the result of the function—or output as we may occasionally call it—is +1, 0, or -1.

Open a new tab in DrRacket and start with a clean slate.

You can define this function in DrRacket without much ado using a conditional expression:
(define (sign x)
  (cond
    [(> x 0) 1]
    [(= x 0)  0]
    [(< x 0) -1]))
 
(sign 10)
(sign -5)
(sign 0)
To illustrate how sign works, we added three applications of the function to the definitions area. If you click RUN, you see 1, -1, and 0.

In general, a conditional expression has the shape
(cond
  [ConditionExpression1 ResultExpression1]
  [ConditionExpression2 ResultExpression2]
  ....
  [ConditionexpressionN ResultExpressionN])
That is, a conditional expressions consists of many conditional lines. Each line contains two expressions: the left one is often called condition and the right one is called result. This is a good time to explore what the STEP button does. Click STEP for the above sign program. When the new window comes up, click the right and left arrows there. To evaluate a cond expression, DrRacket evaluates the first condition expression, ConditionExpression. If the evaluation of ConditionExpression1 yields true, DrRacket replaces the cond expression with the first result expression (ResultExpression1) and evaluates it. Whatever value DrRacket obtains is the result of the entire cond expression. If the evaluation of ConditionExpression1 yields false, DrRacket drops the first line and moves on to the second line, which is treated just like the first one. In case all condition expressions evaluate to false, DrRacket signals an error.

(define (create-rocket-scene.v2 height)
  (cond
    [(<= height 100)
     (place-image  50 height (empty-scene 100 100))]
    [(> height 100)
     (place-image  50 100 (empty-scene 100 100))]))

Figure 1: Landing a rocket (version 2)

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 100 scene. Since the create-rocket-scene function consumes the height at which it is to place the rocket in the scene, a simple test comparing the given height to the maximum height appears to suffice.

See figure 1 for the revised function definition. In BSL, you can really use all kinds of characters in function names, including “.” or “-” which you have already seen. We call the revised function create-rocket-scene.v2 to distinguish it from the original version. Doing so also allows us to use both functions in the interactions area of DrRacket and to compare their results:
> (create-rocket-scene 5555)

image

> (create-rocket-scene.v2 5555)

image

No matter what number over 100 you give to create-rocket-scene.v2, you get the same scene. In particular, when you run the simulation

> (animate create-rocket-scene.v2)

the rocket descends, sinks half way into the ground, and finally comes to a halt.

Landing the rocket half-way under ground is ugly. Then again, you basically know how to fix this aspect of the program. As you learned from the preceding sections, DrRacket knows an arithmetic of images. Images have a center point and, when place-image adds an image to a scene, it uses this center point as if it were the image. This explains why the rocket is half way under ground at the end: DrRacket thinks of the image as if it were a point, but 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, which is to images like + is to numbers. This function comes in handy here because you really want to fly the rocket only until its bottom touches the ground.

Putting one and one together—also known as playing around—you can now figure out that

(- 100 (/ (image-height ) 2))

is the point at which you want the rocket to stop its descent. Hint: you could figure this out by playing with the program directly. Or you can experiment in the interactions area with your image arithmetic. Enter this expression, which is one natural guess:
(place-image  50 (- 100 (image-height ))
             (empty-scene 100 100))
and then this one:
(place-image  50 (- 100 (/ (image-height ) 2))
             (empty-scene 100 100))
Which result do you like better?

(define (create-rocket-scene.v3 height)
  (cond
    [(<= height (- 100 (/ (image-height ) 2)))
     (place-image  50 height (empty-scene 100 100))]
    [(> height (- 100 (/ (image-height ) 2)))
     (place-image  50 (- 100 (/ (image-height ) 2))
                  (empty-scene 100 100))]))

Figure 2: Landing a rocket (version 3)

When you think and experiment along these lines, you eventually get to the program in figure 2. 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 imagine this. Your manager at your hot game company doesn’t like flight simulations where rockets that sink halfway into the ground. Worse, all of a sudden, this manager requests a version of the game that uses 200 by 400 scenes. This simple request forces you to replace 100 with 400 in five places in the program, which includes the animate line, and to replace 100 with 200 in three other places. 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 real programs consists of 50,000 or 500,000 or 5,000,000 lines of code.

In the ideal program, a small request, such as changing the sizes of the canvas, should require an equally small change. The tool to achieve this simplicity with BSL is define. In addition to defining functions, you can also introduce constant definitions, which assign some name to a constant. The general shape of a constant definition is straightforward:

(define Name Expression)

Thus, for example, if you write down

(define HEIGHT 100)

in your program, you are saying that HEIGHT always represents the number 100. The meaning of such a definition is what you expect. Whenever DrRacket encounters HEIGHT during its calculations, it uses 100 instead. Of course, you can also add

(define WIDTH 100)

to your program to have one single place where you specify the width of the scene.

(define (create-rocket-scene.v4 h)
  (cond
    [(<= h (- HEIGHT (/ (image-height ) 2)))
     (place-image  50 h (empty-scene WIDTH HEIGHT))]
    [(> h (- HEIGHT (/ (image-height ) 2)))
     (place-image  50 (- HEIGHT (/ (image-height ) 2))
                  (empty-scene WIDTH HEIGHT))]))
 
(define WIDTH 100)
(define HEIGHT 100)

Figure 3: Landing a rocket (version 4)

Now take a look at the code in figure 3, which implements this simple change. Copy the program into DrRacket, and after clicking RUN, evaluate the following interaction:

> (animate create-rocket-scene.v4)

Confirm that the program still functions as before.

The program in figure 3 consists of three definitions: one function definition and two constant definitions. The number 100 occurs only twice: once as the value of WIDTH and once as the value of HEIGHT. The last line starts the simulation, just as in version 3 of the program. You may also have noticed that it uses h instead of height for the function parameter of create-rocket-scene.v4. Strictly speaking, this change isn’t necessary because DrRacket doesn’t confuse height with HEIGHT but we did it to avoid confusing you.

When DrRacket evaluates (animate create-rocket-scene.v4), it replaces HEIGHT with 100 and WIDTH with 100 every time it encounters these names. To experience the joys of real programmers, change the 100 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.

In modern parlance, you have just experienced your first program refactoring. Every time you re-organize your program to prepare yourself for likely future change requests, you refactor your program. Put it on your resume. It sounds good, and your future employer probably enjoys reading such buzzwords, even if it doesn’t make you a good programmer. What a good programmer would never live with, however, is that the program contains the same expression three times:

(- HEIGHT (/ (image-height ) 2))

Every time your friends and colleagues read this program, they need to understand what this expression computes, namely, the distance between the bottom of the screen and the center point of a rocket resting on the ground. Every time DrRacket computes the value of the expressions it has to perform three arithmetic operations: (1) determine the height of the image; (2) divide it by 2; and (3) subtract the result from 100. And every time it comes up with the same number.

This observation calls for the introduction of one more definition to your program:
(define ROCKET-CENTER-TO-BOTTOM
  (- HEIGHT (/ (image-height ) 2)))
plus the replacement of every other occurrence of (- HEIGHT (/ (image-height ) 2)) with ROCKET-CENTER-TO-BOTTOM. You might wonder whether the new definition should be placed above or below the definition for HEIGHT. More generally, you should be wondering whether the ordering of definitions matters. The answer is that for constant definitions, the order matters, and for function definitions it doesn’t. As soon as DrRacket encounters a constant definition, it determines the value of the expression and then associates the name with this value. Thus, for example,
(define HEIGHT (* 2 CENTER))
(define CENTER 100)
is meaningless because DrRacket hasn’t seen the definition for CENTER yet when it encounters the definition for HEIGHT. In contrast,
(define CENTER 100)
(define HEIGHT (* 2 CENTER))
works as expected. First, DrRacket associates CENTER with 100. Second, it evaluates (* 2 CENTER), which yields 200. Finally, DrRacket associates 200 with HEIGHT.

While the order of constant definitions matters, it doesn’t matter whether you first define constants and then functions or vice versa. Indeed, if your program consisted of more than one function, it wouldn’t matter in which order you defined those. For pragmatic reasons, it is good to introduce all constant definitions first, followed by the definitions of important functions, with the less important ones bringing up the rear guard. When you start writing your own multi-definition programs, you will soon see why this ordering is a good idea.

; constants
(define WIDTH  100)
(define HEIGHT 100)
(define MTSCN  (empty-scene WIDTH HEIGHT))
(define ROCKET )
(define ROCKET-CENTER-TO-BOTTOM
  (- HEIGHT (/ (image-height ROCKET) 2)))
 
; functions
(define (create-rocket-scene.v5 h)
  (cond
    [(<= h ROCKET-CENTER-TO-BOTTOM)
     (place-image ROCKET 50 h MTSCN)]
    [(> h ROCKET-CENTER-TO-BOTTOM)
     (place-image ROCKET 50 ROCKET-CENTER-TO-BOTTOM MTSCN)]))

Figure 4: Landing a rocket (version 5)

The program also contains two line comments, introduced with semi-colons (“;”). 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 4. 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.

Before you read on, ponder the following changes to your program:
  • 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 per se 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.

Better than pondering is doing. It’s the only way to learn. So don’t let us stop you. Just do it.

Magic Numbers Take another look at the definition of create-rocket-scene.v5. As 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 whimsical choice for an x coordinate for the rocket. Even though 50 doesn’t look like much of an expression, it actually is a repeated expression, too. In other words, we have two reasons to eliminate 50 from the function definition, and we leave it to you to do so.

One More Definition

Danger ahead! This section introduces one piece of knowledge from physics. If physics scares you, skip this section on a first reading; programming doesn’t require physics knowledge. Real rockets don’t descend at a constant speed. Real cars don’t stop on the spot. They decelerate, which is the opposite of accelerate. What this really means is that an object first travels at a constant speed and then the driver hits the brakes or the pilot fires some engines. The effect of using the brakes or firing the engines is to change the speed slowly—decelerate in fancy English.

To understand how this process works precisely, you must think back to your physics courses. If you haven’t because you’re too young or if you can’t remember because you’re too old or if you fell asleep in the course, you’ll need to look in a physics book. Don’t worry. This happens to programmers all the time because they need to help people in music, physics, mechanical engineering, economics, photography, and all kinds of other disciplines and, obviously, not even programmers know everything. So they look it up. Or they are told what deceleration means in terms of distance traveled:

That is, if v is the speed of the object and a is the deceleration—change of speed—then the object travels d miles (or meters or pixels or whatever) in t seconds.

By now you know that a good teacher would have shown you a proper function definition:

because this tells everyone immediately that the computation of d depends on t and that v and a are constants. A programmer goes even further and uses meaningful names for these one-letter abbreviations:
(define VELOCITY 20)
(define DECELERATION 1)
 
(define (distance t)
  (- (*  VELOCITY t) (* 1/2 DECELERATION (sqr t))))
This program consists of three definitions: a function that computes the distance traveled by a decelerating object; its velocity or speed for you; and its change in speed or deceleration. The distance function uses a primitive operator called sqr; if you can’t figure out what it does, play with it in the interactions area or look it up in HelpDesk.

The next and only other thing you need to know is that animate actually applies its functions to the number of clock ticks that have passed since it was first called and not the height of the rocket image. From this revelation it immediately follows that our five versions of create-rocket-scene have thus far used the wrong name for the input. Clearly, tshort for time—would be much better than h, which is short for height:
(define (create-rocket-scene t)
  (cond
    [(<= t ROCKET-CENTER-TO-BOTTOM)
     (place-image ROCKET X t MTSCN)]
    [(> t ROCKET-CENTER-TO-BOTTOM)
     (place-image ROCKET X ROCKET-CENTER-TO-BOTTOM MTSCN)]))
More importantly, however, this small change to the definition also clarifies that this program doesn’t compute how far the rocket has traveled in the given time; it uses the time as if it were a distance.

; properties of the world
(define WIDTH  100)
(define HEIGHT 100)
 
; properties of the descending rocket
(define VELOCITY 20)
(define DECELERATION 1)
 
; various other constants
(define MTSCN  (empty-scene WIDTH HEIGHT))
(define ROCKET )
(define ROCKET-CENTER-TO-BOTTOM
  (- HEIGHT (/ (image-height ROCKET) 2)))
 
(define X 50)
 
; functions
(define (create-rocket-scene.v6 t)
  (cond
    [(<= (distance t) ROCKET-CENTER-TO-BOTTOM)
     (place-image ROCKET X (distance t) MTSCN)]
    [(> (distance t) ROCKET-CENTER-TO-BOTTOM)
     (place-image ROCKET X ROCKET-CENTER-TO-BOTTOM MTSCN)]))
 
(define (distance t)
  (- (* VELOCITY t) (* 1/2 DECELERATION (sqr t))))

Figure 5: Landing a rocket (version 6)

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. Instead of t, we use (distance t), and we add the above definitions to our program. The final program is displayed in figure 5. It consists of two function definitions: create-rocket-scene.v6 and distance. The remaining constant definitions make the function definitions readable and modifiable. As always, you can run the program by supplying one of its functions to animate:

> (animate create-rocket-scene.v6)

In comparison to the previous versions of create-rocket-scene, this final version teaches you that a program may consist of more than one function definition and that one function definition (create-rocket-scene.v6) can refer to other function definitions (distance).

In a way, this revelation shouldn’t surprise you. Even the first version of create-rocket-scene used + and / and other functions. It’s just that you think of those as built into DrRacket. While + and / are indeed an intrinsic part of the programming language, some others are not. For example, most of the “image arithmetic” and a good part of the “string arithmetic” are just function definitions that we created a long time ago and that are added to your definitions area when you click RUN.

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 such collections of definitions so that you can read them easily even months after completion. After all, you or your manager will want to make changes to these programs, and if you don’t know how to read them and if you didn’t organize them well, you will have a difficult time with even the smallest task. Otherwise you mostly know what there is to know and you can program.

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 is to know. You know that programming and computing is about arithmetic of numbers, strings, images, and whatever other data your chosen programming languages supports. 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 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 "universe" teachpack provide 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.

From a theoretical perspective, you are missing one piece of the puzzle: the ability to define functions that, when called, compute forever. This may sound useless and difficult to achieve. It is neither. Here is how you define such a program:

(define (run ul)
  (run 42))
 
(run 5)

If you click RUN, you get no result. Actually, you should immediately move the mouse to the STOP button, click, hold the mouse button down, and wait for DrRacket to stop your run-away program.

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.

Stop! Think! Don’t turn the page yet.

Not!

When you look at the “programming” book shelves in any random book store of some unnamed book chain, not to speak of certain parts of college book stores, you will see loads of books that promise to turn lead into gold, that is, make you a programmer in 21 days or faster. There are also books by cautious authors who think you need to stretch the same or similar material over the entire course of a semester. If you have worked through the first six sections of this book, however, you know that neither of these approaches can create a solid understanding of programming.

Acquiring the mechanical skills of programming—learning how to write instructions or expressions that the computer understands, getting to know what functions are available in the libraries, and similar activities—aren’t helping you much with real programming. To make such claims is like saying that a 10-year old who knows how to dribble can play on a professional soccer (football) team. It is also like claiming that memorizing a thousand words from the dictionary and a few rules from a grammar book teaches you a foreign language.

Programming is far more than the mechanics of language acquisition. It is about reading problem statements, extracting the important concepts. It is about figuring out what is really wanted. It is about exploring examples to strengthen your intuitive understanding of the problem. It is about organizing knowledge and it is about knowing what you don’t know yet. It is about filling those last few gaps. It is about making sure that you know how and why your code works, and that you and your readers will do so in the future. In short, it is really about solving problems systematically.

The rest of this book is all about these things; very little of the book’s content is about the mechanics of BSL or other HtDP languages. The book shows you how good computer programmers think about problems, and—promise!—you will even learn to see that these ideas of problem solving apply to other situations in life, e.g., the work of doctors and journalists, lawyers and engineers, or car mechanics and photographers.

Oh, and by the way, the rest of the book uses a tone that is appropriate for a serious text.

What the book is not about: Many early books on programming and even some of today’s books teach you a lot about the authors’ favorite application discipline for programming: mathematics, physics, music, accounting, and so on. To some extent that is natural, because programming is useful in those areas. Then again, it forces you to know a lot (or at least something) about those disciplines. This book really focuses on programming and problem solving and what computer science can teach you in this regard. We have made every attempt to minimize the use of knowledge from other areas; for those few occasions when we went too far, we apologize.