On this page:
1.1 Arithmetic and Arithmetic
1.2 Inputs and Output
1.3 Many Ways to Compute
1.4 One Program, Many Definitions
1.5 One More Definition
1.6 You are a Programmer Now
1.7 Not!

1 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 DrScheme and choose the Beginning Student Language with the “Language” menu: see the “How to Design Programs” submenu. Now you’re ready.

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 DrScheme, click RUN, and a result shows up in the bottom part: 2

You should also have noticed a warning about testing. Don’t ignore it forever but just for this Prologue.

That’s how simple programming is. You ask questions as if DrScheme were a child, and DrScheme computes for you.

People often say the “computer computes for you” but in reality, raw computers do nothing. A raw computer is pretty useless to most people. It is software that really makes computers useful to them and you, it is just difficult to get used to saying “the software computes for you.”

You can also ask DrScheme 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 DrScheme, which are the correct results. This means that DrScheme knows a lot about arithmetic, far more than a small child. Indeed, DrScheme knows about squaring numbers, exponents, and even trigonometry:
  (sqr 3)
  (expt 2 3)
  (sin 0)
  (cos pi)
When you click RUN now, DrScheme’s bottom half displays four numbers: 9 8 0 #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.” Unlike your calculator or most other programming systems, DrScheme 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 DrScheme issues such warnings.

Terminology: At this point, we should slow down for just a moment and introduce some words:
  • The top-half of DrScheme is called the definitions area. This area is where 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, DrScheme asks you for the name of a file, which is a place on your computer (technically, its disk) where DrScheme stores your program for good. Once your definitions area is associated with a file, clicking SAVE just ensures that the content of the definitions area is stored safely in the file.

  • Programs consists of expressions. For now, programs are 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 DrScheme rewards by displaying a gray box.

  • When you click RUN, DrScheme evaluates an expression at a time and displays the result in the interactions area. Then, DrScheme, your faithful servant, awaits your commands at the prompt and you can enter additional expressions though they disappear next time you hit RUN:

      > (+ 1 1)

      2

    Enter your first program at the prompt, hit the “return” or “enter” key on your keyboard, and watch how DrScheme 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

Enough memorizing.

By now, you might be wondering whether DrScheme 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 Scheme arithmetic and it is natural, if you always use parentheses to group operations and numbers together. This as a good a time as any to discuss the nature of our notation – dubbed Beginning Student Language or just BSL – something you might have pondered for a while now.

You might be thinking that you’re learning Scheme because the software application is called DrScheme. Not true, however. You are learning a series of teaching languages created for this book, starting with BSL. These teaching languages are to Scheme what American English is to British English. Once you have mastered these languages though, you can quickly learn all kinds of languages and especially PLT Scheme, a power tool with which you can easily create all kinds of interesting programs.

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 DrScheme calculates for you, it uses the rules that you know and love (or don’t). Like you, it can determine the result of an addition only when all the operands are numbers. If an operand is an expression, it determines the result of that expression first. Unlike you, it never needs to ponder with which expression to calculate first – because the first rule is the only rule there is to it. The price for DrScheme’s convenience is that you, the programmer, must enter all these parentheses. Once you get used to BSL programming though, you will see that it isn’t a price at all. For one, 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 DrScheme’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" key; DrScheme lets you know whether it works. For two, 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.

In short, to program is to write down arithmetic expressions, and to compute is to determine their value. The place to write down expressions is the definitions area. Clicking RUN makes DrScheme compute the values of these expressions, which it then displays in the interactions area.

1.1 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, DrScheme 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 DrScheme 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, DrScheme 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 strings; make all letters uppercase (or lowercase) in a string; 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 DrScheme 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 “fortytwo” 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, booleans come in only two varieties: true and false. The first is truth, the second falsity. Even so, DrScheme has several operations for combining booleans:
  > (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 (<= -1 -1).

With all these new kinds of data – yes, numbers, strings, and booleans 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 DrScheme’s interactions area and hit the "return" key? If you did the latter, do you think you would know how to do this in your own? After all, if you can’t predict what DrScheme does for small expressions, you may not want to trust it when it works on larger tasks than that for you.

Before we show you how to do some “real” programming, let’s discuss one more kind of data to spice things up:

To work with images such as this rocket, use the Insert menu, select the “Insert image ...” item, and choose your image via the file system browser. Or, if you’re reading this book on-line, copy-and-paste the image from your browser into DrScheme via right-click.

>

In contrast to other programming languages, DrScheme understands images and can calculate with them. Furthermore DrScheme 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.

It’s time to add the "universe" teachpack to DrScheme. Use the “Language” drop-down menu, choose “Add Teachpack ...” and then pick "universe". This library provides primitives for manipulating images and for other fun things.

One important library – "universe" – 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 DrScheme programs with the “Insert” menu. You can also instruct DrScheme to create simple images from scratch:
  (circle 10 "solid" "red")
  (rectangle 30 20 "outline" "blue")

If you are reading the paper version of the book, though, you only see a gray circle and a gray, outlined rectangle.

What you should see is a solid red circle of radius 10 and the blue outline of a 30 by 20 rectangle:

Naturally BSL has operations for combining images:
  (overlay (rectangle 20 20 "solid" "blue")
           (circle 5 "solid" "red"))
produces a red circle on a solid blue square background:

Overlaying the same images in the opposite order, like this,
  (overlay (circle 5 "solid" "red")
           (rectangle 20 20 "solid" "blue"))
produces a solid blue square Now you know that overlay is more like string-append than +, but it does “add” images just like string-append “adds” strings and + adds numbers.

Do yourself a favor and look up the documentation for overlay/xy in HelpDesk. Then experiment with the function, which is also available through the "universe" teachpack.

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:

As you can see from this image (which superimposes a grid on the empty scene), 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, booleans, 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.

1.2 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 DrScheme 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, booleans, 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:

x =

1

2

3

4

5

6

7

8

9

10

y =

1

4

9

16

25

36

49

64

81

?

Your teachers would show you those, and then they’d ask you to fill in the blanks (replace the “?” marks).

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:

Yes, 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 y – just 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 DrScheme, 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, DrScheme 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, DrScheme 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 DrScheme. It is as if you hadn’t accomplished anything. But you did. You actually defined a function and informed DrScheme 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 DrScheme.

... 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, DrScheme 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 word “define,” a keyword or marker whose sole purpose is to distinguish a definition from expressions. 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 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. Naturally, the expression may consist of many other expressions, as we have seen in the first two sections.

Second,

(FunctionName ArgumentExpression)

is a function application. The first part tells DrScheme 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.

The second goal requires knowledge about one additional primitive operation: animate. Here is how you use it:
  (animate create-rocket-scene)

When you add this expression at the bottom of the definitions area and click RUN, DrScheme evaluates the expression and does not display a result, not even an interactions prompt (for a while). It does open another window (a canvas) and runs a little “movie” that shows the rocket descending from the top of the screen to the bottom where it then disappears.

You should eventually dismiss this extra window, at which point DrScheme displays a number in the interactions area (the height of the rocket at that point).

Yes, the operand is a function here. Don’t worry for now about using functions as operands. Don’t try this on your on, however, unless we ask you to do it or until we explain what this is all about.

The question is where the images on the window come from, and to that end, animate looks at its operand: create-rocket-scene.

Based on this explanation, you can also imagine what happens:
  • animate starts a clock;

  • the clock “ticks” many times per second; to be precise, the clock ticks 28 times per second, and you could change this if you wanted to;

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

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

The only question is to what create-rocket-scene is applied. The answer is that it is applied to the number of times the clock has ticked since the beginning of time: 1, 2, 3, and so on. 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. In short, our three-line program creates some 100 pictures in about 3.5 seconds and these pictures are displayed to create the effect of a rocket moving through space.

Here is what you learned in this section. Programs are useful because they can compute lots of data in a short time. They do so with functions, which produce different outputs from different inputs. You can launch these functions on a few simple inputs to ensure that they work properly, and DrScheme can launch these functions many times per second.

Indeed, DrScheme can also launch functions when you press a key on your keyboard or when you manipulate the mouse. To find out more, read the documentation for the "universe" teachpack or keep reading this book.

The former is what people call “testing” a function, and the latter is what is really called “running a program” or “launching a program.” Whatever triggers a function application isn’t important, as long as you keep in mind that (simple) programs are just functions.

1.3 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 DrScheme and start with a clean slate.

You can define this function in DrScheme 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)
The results of the three applications are just as expected: 1 -1 0.

Naturally, a conditional expression may contain arbitrary expressions instead of plain numbers next to the conditions. In general, a conditional expression has the shape:
  (cond
    [ConditionExpression1 ResultExpression1]
    [ConditionExpression2 ResultExpression2]
    ....
    [ConditionexpressionN ResultExpressionN])
That is, a conditional expressions consists of many lines and each line contains two expressions: the left one is often called condition and the right one is called result.

To evaluate a cond expression, DrScheme evaluates the first condition expression (ConditionExpression). If the evaluation of ConditionExpression1 yields true, DrScheme replaces the cond expression with the first result expression (ResultExpression1) and evaluates it. Whatever value DrScheme obtains then is the result of the entire cond expression.

This is a good time to explore what the STEP button does for you. Go ahead, click! And when the new window comes up, keep clicking STEP there.

If the evaluation of ConditionExpression1 yields false, DrScheme 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, DrScheme signals an error.

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:
  (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))]))
Adding (create-rocket-scene 5555) and clicking RUN would have produced an empty scene In contrast, (create-rocket-scene.v2 5555) shows the rocket at the bottom of the scene:

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, DrScheme 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: DrScheme 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 it 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?

When you think and experiment along these lines, you eventually get to this program:
  (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))]))
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.

1.4 One Program, Many Definitions

Believe it or not, a computer programmer could easily live with a rocket that lands halfway under ground. What a good programmer would never live with, however, is that the program contains the same expression three times:
  (- 100 (/ (image-height ) 2))
Every time your friends and colleagues read this program, they need to understand what it does, namely, to compute the distance between the bottom of the screen and the center point of a rocket resting on the ground. Every time DrScheme 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.

Neither you nor the computer should repeat such work because it makes your daily life as a programmer difficult. To understand this remark, imagine yourself working for some hot game company implementing this wonderful “War of the Worlds” game program where rockets from some remote planet system attempt to land on your world and you must defend it. So far, so good. You know how to write at least one part of this game. All of a sudden, though, your manager makes your life miserable with the request of making the game run as a 200 by 400 scene. 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. Similarly, a programmer would make one small change to avoid the repetition of the expression mentioned at the beginning of this section. The tool to achieve this in DrScheme is define. In addition to defining functions, you can also define variables (names). For example, you can write down
  (define HEIGHT 100)
at the beginning or end of your program to say that HEIGHT (with all capital letters) always represents the number 100. The meaning of such a definition is what you expect. Whenever DrScheme 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. Take a look at the following code:
  (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)
  
  (animate create-rocket-scene.v4)

This program consists of three definitions: one function definition and two variable 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. 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 DrScheme doesn’t confuse height with HEIGHT but we did it to avoid confusing you.

When DrScheme runs the program above, it replaces HEIGHT with 100 and WIDTH with 100 every time it encounters these variable 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 manager probably enjoys reading such buzzwords.

As we worked through your first refactoring, you probably wondered whether this would also work for the expression
  (- 100 (/ (image-height ) 2))
which started this whole discussion. And indeed, if you add
  (define ROCKET-CENTER-TO-BOTTOM
    (- 100 (/ (image-height ) 2)))
to your program, you may replace every occurrence of the expression with the variable name ROCKET-CENTER-TO-BOTTOM. Naturally, re-introducing the number 100 here isn’t a good idea; you should use HEIGHT instead, which also clarifies what this expression computes.

This addition raises the question 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 variable definitions, the order matters. As soon as DrScheme encounters a variable 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 DrScheme hasn’t seen the definition for CENTER yet when it encountered the definition for HEIGHT. In contrast,
  (define CENTER 100)
  (define HEIGHT (* 2 CENTER))
works as you would expect. First, DrScheme associates CENTER with 100. Second, it evaluates (* 2 CENTER), which yields 200. Finally, DrScheme associates 200 with HEIGHT for the rest of the computation.

You may find it surprising, though, that it doesn’t matter whether you first define the variables in your program or the function(s). Indeed, if your program consisted of more than one function, it wouldn’t matter in which order you defined them. Still, it is good to first introduce all the constants, followed by all the important functions and then the less important ones. We know that because you haven’t yet created a program with more than one function definition yet, this discussion is all theory. You will define and enjoy such programs sooner than you know it, however, and then it all becomes practice.

The program also contains two line comments, introduced with semi-colons (“;”). While DrScheme 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 – without making DrScheme do anything about it.

Once you do all these things, you get this program:
  ; 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)))
  
  ; programs
  (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)]))
  
  (animate create-rocket-scene.v5)
It consists of one function definition and five variable definitions. In addition to the computation that determines the distance between the rocket’s center and the bottom of the scene, these variable definitions also factor out (as in “refactor”) 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 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.

1.5 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 breaks or the pilot fires some engines. The effect of using the breaks 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 in ninth grade. If you haven’t because you’re too young or if you can’t remember because you’re too old or if you skipped this course, you 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 the process of deceleration means for the distance that an object travels:

That is, if v is the speed of the object and a is the deceleration – change of speed – then the object travels d miles/meters/pixels 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 would go even further and use meaningful names for these one-letter things:
  (define V 20)
  (define DECELERATION 1)
  
  (define (distance t)
    (- (* V 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, t – short 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 50 t MTSCN)]
      [(> t ROCKET-CENTER-TO-BOTTOM)
       (place-image ROCKET 50 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.

Even if you have never taken a physics course, you know that a time is not a distance. So somehow our program worked by a little bit of an 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 this:
  ; properties of the world
  (define WIDTH  100)
  (define HEIGHT 100)
  
  ; properties of the descending rocket
  (define V 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)))
  
  ; programs
  (define (create-rocket-scene.v6 t)
    (cond
      [(<= (distance t) ROCKET-CENTER-TO-BOTTOM)
       (place-image ROCKET 50 (distance t) MTSCN)]
      [(> (distance t) ROCKET-CENTER-TO-BOTTOM)
       (place-image ROCKET 50 ROCKET-CENTER-TO-BOTTOM MTSCN)]))
  
  (define (distance t)
    (- (* V t) (* 1/2 DECELERATION (sqr t))))
  
  ; run program run
  (animate create-rocket-scene.v6)
It consists of two function definitions: create-rocket-scene.v6 and distance. The remaining variable definitions make the function definitions readable and modifiable.

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 DrScheme. 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 variable 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.

1.6 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 variable 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 DrScheme and the teackpacks support lots of other functions and that DrScheme 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)
    (run))
  
  (run)

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 DrScheme 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.

1.7 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 understand, 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 1,000 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 things truly work and 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.