Hopefully by now I’ve convinced you that programming involves a process of solving your problems in stages. Since most computer programs that you will want to write are too complex to simply type-in, you need to take advantage of the concept of procedural abstraction. Break the problem that you are writing into pieces. Think about what you need to do; of this, think about what you already know how to do.
Start writing your program in pieces. Each piece is written as a procedure which you define. Your procedures are simply lists of instructions. In techie terms, you are using abstraction to make your source code easier to understand and thus easier to write correctly and easier to enhance.
As you think about the steps or as you are typing in instructions, you will recognize similarities or patterns in your code. When you discover a pattern with the same instructions being used over and over again, you can reduce the amount of code by using iteration – you learned about this (the repeat command) in the last lesson. Using iteration makes your program smaller, and so, easier to understand,
But, iteration only lets you eliminate duplicated instructions, identical source code. In this lesson, you will learn how to define procedures that have inputs, also known as parameters. These inputs (their names) are used in the body of the procedure in place of specific (actual) values. When you invoke the procedure, you provide a specific (actual) value to use in place of the input, everywhere its name is in the body of the procedure.
Procedures with inputs allow you to reduce multiple, similar, patterns of instruction sequences to a single instruction. Confused? It will become clearer as this lesson progresses…
Similar, But Different, Boxes
Look at the series of objects in Figure 6.1. What are the similarities of the objects? What are the differences? Take a moment to write your thoughts.
Now, start with the top row of boxes. Write a program which draws the series of growing boxes. Your program should consist of a procedure for each box. Then, write a procedure with the name “main” which contains invocations of these procedures. Finally, invoke “main” to display the row of boxes.
Here are my definitions of the procedures which draw the first couple of boxes and part of the definition of my main procedure.
to box25 repeat 4 [forward 25 right 90] end to box50 repeat 4 [forward 50 right 90] end to main penup setx -250 sety 12 pendown box25 penup setx -200 pendown box50 ... end
Since the procedures draw different sizes of boxes, I’ve given them different names. But, the only difference in the instructions that make-up the body of these procedures is the number of steps that the turtle is told to move forward.
Think about this scenario. Logo doesn’t have an infinite set of forward commands, e.g., “fd25,” “fd50,” “fd75,” etc… There are not commands for all possible right instructions, e.g., “rt30,” “rt45,” “rt90,” etc… There are commands “forward” and “right” which expect an input that specifies the number of steps to move, or the number of degrees to rotate.
We obviously need the capability to define procedures that can be used in a similar manner. We need the ability to define a procedure named box that expects to get a number when it’s invoked. The number will determine the size of each side of the box we draw.
What we need is called an input.
Defining a Procedure With an Input
Here is what we want…
to box :size repeat 4 [forward :size right 90] end
This procedure definition has an input. Similar to the way you name the procedure itself, you give the input a name, an identifier. In this example, I’ve chosen the name size. The colon (“:”) preceding the name (pronounced “dots”) tells the interpreter that this word is an input and that it should use what’s in it.
What do I mean, in it? Well, an input is one kind of a thing that’s called a variable. Variables are containers. Inputs get a value put in them when the procedure they are part of is invoked.
Up until now, all of the programs you’ve written have been composed of commands with literals as arguments. Literals are constants like the number “4” in the repeat instruction in the example above. Every time box is invoked, the <List-of-Instructions> input to the repeat command is performed 4 times.
But now, the input to the forward command is a variable – the input named size. The number of steps that the turtle moves forward is equal to the input provided in an invocation of box. The turtle moves a variable number of steps everytime the Logo interpreter performs the box procedure.
Here’s the TG applet. Type in the example definition of box from above and then invoke it a couple of time with different values as arguments, e.g.,
box 10 box 25 box 100
Then, see what the following repeat instruction does…
repeat 4 [ box 25 box 50 box 75 left 90 ]
|alt=”Your browser understands the <APPLET> tag but isn’t running the applet, for some reason.” Your browser is completely ignoring the <APPLET> tag!|
Does this make sense?
If it’s even the least bit fuzzy, before moving on, check out the way procedure definition with an input was explained in the book: “Thinking About [TLC] Logo” by clicking on this link.
Procedures With Multiple Inputs
So, you’ve reduced the number of procedures for drawing your boxes from five to one.
box25, box50, box75, box100, and box125 ---> box :size
But, if we look at the commands remaining which draw the line of boxes, you should see a pattern. Here is my modified main procedure which draws the line of boxes.
to main penup setx -250 sety 12 pendown box 25 penup setx -200 pendown box 50 penup setx -125 pendown box 75 penup setx -25 pendown box 100 penup setx 100 pendown box 125 end
I instruct the turtle to pick up the pen, move to the location of the lower-left corner of a box, and then put the pen back down.
Oh – I guess I snuck a couple of new commands in on you. You haven’t seen setx or sety (unless you’ve visited Appendix B). The setx and sety commands move the turtle to specific coordinates in TurtleSpace. They take an integer as an input, which is the point to go to.
Back to the problem at hand… Why not move all of the remaining similar instructions into a procedure?
Procedures are allowed to have more than one input. The repeat command has two, a count and an instruction-list.
Write a new procedure named boxAt which has three inputs: the x and y coordinates of the lower-left corner of the box and the size of the box. It should contain the instructions in main that are pretty much the same – the ones that move the turtle to where the box will be drawn. Then, it should invoke box to draw the box.
Why do you think we should not simply modify the box procedure so that it has the three inputs?
Anyhow, once you have made your changes, test what you came up with by trying the following procedure invocations.
boxAt -250 12 25 boxAt -200 12 50 boxAt -125 12 75 boxAt -25 12 100 boxAt 100 12 125
Stop reading until you’ve tried coming up with something.
An important thing to get correct (and learn from this exercise) is the order in which your inputs are provided when you invoke the procedure. The actual values for the x and y coordinates and the size must be provided in a matching order with the inputs in the procedure definition. Specifically, if your definition of boxAt started out:
to boxAt :size :x :y
the test invocations I asked you to try would not do what I wanted them to. The test invocations expect :size to come last.
But, other than this gotcha, multiple inputs are as easy to use as single inputs.
Here is a small program which draws three cubes. Watch how the program is executed, step by step. Especially watch how how the inputs change when the procedures are invoked. As an example, when diamond is invoked, its :steps variable is replaced with a number.
The Turtle’s Pen (Pixel Graphics)
I’m not going to give you the solution for the Boxes program you are writing, but I’ll help you get one step closer. In this section, I’ll tell you a little more about how the turtle draws.
Since our turtle lives inside a computer, the space it draws on is your computer’s display. For you to get the turtle to draw more interesting things, like the solid colored boxes in this lesson’s exercise (Figure 6.1), you need to know a little more about computer displays.
A computer display is made up of a bunch of dots, called pixels, (an abbreviation for picture elements). The pixels are objects arranged in rows and columns, each spaced an equal distance from the others. Each pixel has a value assigned to it which is its color. Back in the first lesson, you got to interact with an applet that demonstrates color values.
So, Figure 2.1 is a nice, abstract, view of our turtle’s world, but here is a more accurate picture:
To display a thin vertical line, the color values of a column of pixels are set to the desired color of the line. If you want a thicker vertical line, you set the color values of the pixels of a group of consecutive columns to the desired color. Figure 6.3 shows a red line that’s a single pixel wide and an orange line that’s three pixels wide. The orange line is actually a very thin rectangle.
There are no Logo commands that let you modify pixels, but the pen that the turtle carries changes pixels as it passes over them. You control the color the pixels get set to with the setpencolor command. You also can control the width of the line that the turtle draws with the setpensize command.
So, the colored boxes that you need to draw to complete this lesson’s main exercise are nothing but rectangles of pixels. How you set them is up to you. Remember back in the lesson where I introduced iteration? We drew points that were actually boxes. There’s another way to create a solid colored box using lots of single-pixel-wide lines. It’s now up to you to figure out how to do it.
Finish Your Program – Add Colored Boxes
Time to finish your program which draws a series of boxes that grow in size. You now should be able to write a procedure which draws a solid colored box. Do it! And, then use it to complete your program for Figure 6.1.
If you are having trouble getting started, refer back to the steps for writing programs that were described in the lesson which introduced procedures. Start by writing everything you know about what needs to be done. Convert this into pseudocode and then into procedures that you write which draw the series of solid colored boxes.
Final Challenges – Additional Exercises
- Your boxes are squares which are special cases of rectangles. Write a couple of procedures that draw rectangles.
- One, rectAt, should take four inputs: a starting position (xPos and yPos), a width and a height and draws a wire-frame rectangle.
- The other, fillRectAt, should take the same four inputs and one additional input, the color, and draws a solid, colored rectangle.
Once you’ve tested them and they are working, modify your Boxes program such that its boxAt procedure invokes your new rectAt procedure and its coloredBoxAt procedure invokes your new fillRectAt procedure.
- The exercise at the end of the last lesson challenged you to take something as simple as an arc and use it to draw a flower (see Figure 5.1). Here is a simple seascape that is also composed with arcs.
Write procedures arc, bird, fish, and waves and then invoke them from a main procedure. Then invoke main to draw your seascape.
In this lesson, you’ve learned how to extend the utility of procedures. You now know how to write procedures that can act differently; exactly what gets done depends upon the inputs ( parameters) that are provided in invocations. This is good for two reasons:
- You can reduce the size of your programs. The shorter your programs are, the easier they are to read and understand, the less chance they have mistakes in them, and the less you have to type.
- Your abstractions can be more powerful. Without inputs, a procedure does the same thing every time it is invoked. This is pretty limiting. But, with inputs, your procedures are much more flexible.
|New Logo Primitive Procedures Used In This Lesson|
|SETX||number||Moves the turtle horizontally to the specified absolute window position.||SETX 100|
|SETY||number||Moves the turtle vertically to the specified absolute window position.||SETY 100|