Background
jLogo Programming
- Commanding a Turtle
- Pseudocode
- Adding New Commands
- Iteration & Animation
- Hierarchical Structure
- Procedure Inputs
- Primitive Operators
- Defining Operators
- Words & Sentences
- User Interface Events
- What If? (Predicates)
- Recursion
- Local Variables
- Global Variables
- Word/Sentence Iteration
- Mastermind Project
- Multiple Turtles
- Arrays
Java
- A Java Program
- What's a Class?
- Extending Existing Classes
- Types
- Turtle Graphics
- Control Flow
- User Interface Events
Appendices
Lastly
Adding Commands
Introduction
procedure n 1 a: a particular way of accomplishing something
or of acting 2: a series of steps followed in a regular
definite order ( Webster's New Collegiate Dictionary )
In this lesson you will learn how to teach the Logo interpreter, embedded in TG, new commands. When you startup TG, its Logo interpreter only understands the commands that are built into it, also known as the basic primitive procedures of the Logo language. You will learn how to add words to its vocabulary; you will teach it how to do something it does not yet know how to do.
This capability of naming a procedure (a list of instructions) for doing something, is very powerful. The new named procedure will be made up of instructions that the interpreter already knows how to perform, already existing procedure names in its vocabulary. As you are about to learn, writing your own (a.k.a. user-defined) procedures will be a big help when you construct large programs. It will help you write programs that actually do what you want them to do.
Starting with this lesson, I want you to think of writing programs as a process of inventing a language that you then use to instruct the computer to do what you want.
Procedural Abstraction
In the last lesson, I stressed the importance of breaking your programs into pieces. Each piece was labeled with a pseudocode comment and thus easy to understand. Your program was the concatenation of the pieces.
This approach is very important for writing programs that are easy to read and understand, and most importantly, do what you want them to do. You may be questioning: "Why is it so important to write a program that is easy to read?". The reason is that most programs are enhanced, both during development in stages and for years after the first version is complete.
Programs that you write need to be structured so that they can be understood a long time after you think you are done with them.
For review, here are our steps in the programming process:
- think about what you have to do and approaches to it,
- break up the program into pieces written in pseudocode, and
- convert the pseudocode to Logo instructions and type them in.
Now let's look at what can often be an alternative to pseudocode. For simple, small pieces of a program we are writing, there's an alternative for pseudocode. Pseudocode is just our thoughts about breaking down a problem into understood pieces. Now let's use Logo's capability for extension, its ability to accept new command definitions, to achieve the same result.
Writing our own Logo commands will get us procedural abstraction, an important separation of the description of what something does from how it does it. For now, don't worry about this technical term. Just think of it as jargon for inventing new commands that do one thing, something that is the first thing you think of when you hear the name you give to the command. So, the names we give the new commands need to be a substitute, an abbreviation, for the text of the pseudocode we would have written. So, the choice you make for the name of your new command is very important.
Procedural abstraction is one of the most important programming concepts you will learn.
So, how do we do this? Let's work through an example. It will give you a good feel for what I'm attempting to cover in this lesson. Write a program that draws a three to five letter word, a name of some sort...
Practice: Draw a Word
Write a program that draws a three to five letter word, a name of some sort... I picked the name of our programming language: LOGO.
Here is the TG applet; click the mouse in the Editor and type in your pseudocode, then instructions that draw the word. Follow the process that was covered in the previous lesson.
TG - TurtleGraphics Applet
Figure 4.1 shows what I came up with. I drew the word "LOGO" in uppercase.
Figure 4.1
Introducing "TO"
Table 4.1 shows the pseudocode descriptions of what I did to draw the word "LOGO" and their comparable lists of Logo instructions.
| Pseudocode | Logo Instructions |
|---|---|
| ;draw 'L' | fd 100 bk 100 rt 90 fd 50 |
| ;move to starting position ;for the next character |
pu fd 15 |
| ;draw 'O' | pd fd 50 lt 90 fd 100 lt 90 fd 50 lt 90 fd 100 |
| ;move to starting position ;for the next character |
pu lt 90 fd 65 |
| ;draw 'G' |
pd lt 90 fd 100 rt 90 fd 50 bk 50 lt 90 bk 100 rt 90 fd 50 lt 90 fd 50 lt 90 fd 20 |
| ;move to starting position ;for the next character |
pu bk 20 rt 90 bk 50 rt 90 fd 15 |
| ;draw 'O' | pd fd 50 lt 90 fd 100 lt 90 fd 50 lt 90 fd 100 |
| |
|
Here are a few problems I have with this program, these lists of instructions.
- the pseudocode is only a comment and its relation to the instructions it pertains to is purely positional. There is no guarantee it matches what the instructions do. If the Logo instructions are edited/changed so they no longer match the pseudocode/comment, we have a BIG problem. Erroneous comments are worse than none at all. A reader assumes she can no longer trust any comments.
- if the instructions are moved around and/or combined with others it will be hard to figure out if this new combination of instructions and associated pseudocode still match,
- in this program, each letter is drawn separately (O is drawn twice, with two lists of instructions). This means more typing than we would ideally perform. Think about how big your program would be if you drew MISSISSIPPI even though it is made up of only four characters.
Definition of a Procedure
There is a another way to tag meaning to a list of instructions - to give the list a name, an identifier. You can teach the Logo interpreter to do something. As the user of TG, you can define a new command, a new procedure for doing something.
Here's how to define a new command that draws the letter O.
|
Here is another definition that accomplishes the same thing.
|
I prefer the first definition. It is easier to read and with the symmetry of the four forward commands; you can see what is going on, that it is correct - going to do what you want it to.
So, what have we done here?
We've used a special kind of command, a directive ("to"), to teach the Logo interpreter a new command. Just as it understands "forward" and "left" commands, it now knows the comand name "drawO" and what it means, what it consists of. Since you defined it, it's called a user-defined procedure.
"TO" in Detail
The general form, the syntax, of "TO" (a procedure definition) is:
| to | <name> |
| <Logo-Instructions> | |
| ... | |
| end |
Procedure definitions consist of:
- a title line (the "to" line containing the procedure's name, its identifier),
- a body consisting of one or more lines of instructions, and
- an end line (the word "end")
Practice: Define the Procedure drawO
Either go back up to the TG applet or use a small popup TG applet to type in the definition of drawO. You can type the definition into either the CommandCenter or Editor. No matter which you choose, you will notice that TG behaves differently when you define a new command. Let's start with defining a new command in the CommandCenter.
In the past, every time you typed instructions into the CommandCenter, when you pressed the [Enter] key, something happened. When you typed "fd 100" into the CommandCenter and pressed [Enter], the turtle would move forward in the graphics area. But, when you type in the title line of your new command and press [Enter], the way TG responds is different. As Figure 4.3 show, the '?' prompt character you've been accustomed to has changed to '>' and the cursor is indented a couple of spaces.
Figure 4.3
And now as you type in the lines of instructions that make up the body of the drawO command, nothing happens in the graphics area. Instead, TG keeps responding to your pressing the [Enter] key with another '>' prompt character and with the cursor indented. And, it keeps doing this until you enter the end line. Figure 4.4 shows TG following the entering of the end line. All is back to normal.
Figure 4.4
The CommandCenter is great for adding a trivial command when you just want to experiment. But, once you've entered a line of instructions, that's it; there's no going back to change them. You must quit the current definition (either by entering an end line or by holding down the [Ctrl] key and pressing Q - the QUIT directive) and then start all over. This is not too bad since you can use the up/down arrow keys to recall previously entered lines; but using the Editor is better if you think you may need to change your definition.
Figure 4.5 is a snapshot of TG after the title line of drawO has been entered in it. In this case, the editor has added an end line for you automatically, opened a blank line between the title line and the end line, and the cursor is indented ready for you to start typing in the body of the command. And to make it easier for you to read, the title line and the end line are colored green and emboldened.
Figure 4.5
As you type in each line of instructions for the body of drawO and press the [Enter] key, the Editor will open a new blank line and properly indent for you.
Once you've defined drawO you can use it like any of the Logo commands you've been using. You've just taught the Logo interpreter how to do something; you've added a new command to Logo's vocabulary.
Try out your new command. In the CommandCenter, type "drawO" and press [Enter] to see what this does. Did it do what you expected?
If not, the next section may help you find your problem.
Problem Solving: Procedure Definitions
There are two kinds of problems you must deal with when you are writing programs, syntax errors and logic errors. Syntax errors occur when you type something in that the Logo interpreter does not understand. Figure 4.6 shows what happens when you forget to supply a number of turtle steps after the forward command's name.
Figure 4.6
Figure 4.7 shows what happens when you accidently press the lower-case 'o' key instead of the zero key.
Figure 4.7
In this example, when Logo interpreted the forward command, it read the next word expecting to get a number. Instead it got a word consisting of a digit and then a couple of letters. In this situation, Logo looks to see if there is a procedure with this word ("1oo") as its name. Since it's actually a mistake and so it does not find one, it complains that it does not know how to do anything named "1oo".
When you type command definitions in via the CommandCenter and get a syntax error in the process, you don't always end up with what you think you should.
Here are a couple of diagnostic commands (directives) that may help you with problems associated with user-defined procedures. Even if your drawO procedure did work, you probably should try these commands.
| TG Directive | Description | Example |
|---|---|---|
|
printprocs pp |
Print a list of user-defined procedures the Logo interpreter in TG knows about. |
? printprocs drawO ? |
|
printtext pt |
Print the text (the source code representation) of a specified user-defined procedure. |
? printtext drawO to drawO pd fd 50 lt 90 fd 100 lt 90 fd 50 lt 90 fd 100 end ? |
| |
||
Click the mouse in the CommandCenter and enter the command:
|
The name of your new procedure, drawO, should be printed. If it is, next try:
|
"printtext drawO" asks the Logo interpreter in TG to print out the definition of the drawO command. If your command did not work, check it out to see what's wrong. Reenter the definition until it matches what one of the above examples looks like.
Ok, now for the hardest kind of error to correct, a logic error. If you typed the drawO procedure in exactly as it was presented, you probably didn't get a properly drawn O when you tested it. Chances are, your O was laying down on its side. Why? Think about it for a bit before reading on...
The reason is that when I wrote the pseudocode and instruction list program, the O always followed another letter. So the code that moved the turtle from where the previous letter ended to the lower-left corner of the O left the turtle heading to the east. This is called a logic error because our drawO procedure made an assumption that was not always the case.
The proper way to fix this is to add an instruction at the beginning of our definition to set the turtle's heading to be east, ninety degrees in TurtleSpace. Here's the description of command you now need.
| Command | Input | Description |
| SETHEADING | number |
Turns the turtle to a new absolute heading. The input,
number, is the heading in degrees clockwise from the
positive Y axis, i.e.,
0 is due North (up),
90 is due East (right),
180 is due South (down), and
270 is due West (left).
|
| |
||
And now, with setheading, here's the new definition of drawO.
|
Now we have a drawO that will always draw a proper O. What we've done is to generalize the drawO procedure. It can work in a more general setting. This is an important trait of a well-written procedure. In fact it is so important that I'll cover in a dedicated section of this lesson. But before that...
Practice:
Define Procedures for Other Letters
Define commands for all of the letters in the word that you chose to draw back at the beginning of this lesson. Use the TG application if you have it, otherwise either go back up to the TG applet or use this small popup TG applet. Use the editor to define your commands so that you can change them.
As you define them, test them by invoking the new commands in the CommandCenter. Make sure they do what you want.
Here are my definitions of drawL and drawG:
|
Take a few minutes to read my definitions closely. Notice that the bodies of these commands do not match the instruction lists in Table 4.1.
What is the big difference?
Hint: the answer I'm looking for has to do with the logic, not the syntax (yes, the primitive command names are abbreviated in Table 4.1 and not in the command definitions). But that's not the answer I'm looking for.
Why do you think I've made the changes?
Hint: I'm thinking ahead to when I'm going to put drawL, drawO, and drawG together, along with the need to move the turtle to where each letter needs to be drawn.
Generalization and Black Boxes
As I hinted, the changes made when I defined drawL and drawG were made in anticipation of putting all the letters together to form the word LOGO. What would all the code look like if I had not made any changes? Here is what I would have:
|
The problem with this program shows up in two ways.
- In this program, I have the same comment in three places, but the instruction lists associated with them are all different. This hints at the real problem...
- The instructions that move the turtle from where the L ended to where the O begins depend upon knowing where the drawL command left it. Similarly, the instructions that move the turtle from where drawO left the turtle to where drawG starts has a similar problem. And, there's the same problem going from the G to the final O.
Here's the way to fix the problem in the language of computer programmers: "All of our command definitions must be written to specifications provided as a contract. They are then to be treated as black boxes." Now let me explain what this means.
Black box is technical jargon for a device or system
or object when it is viewed primarily in terms of its
input and output characteristics. Almost anything might
occasionally be referred to as a black box: a transistor,
an algorithm, humans, the Internet. ( WikipediA )
All of the procedures I wrote above (drawL, drawO, and drawG) follow a specification:
Draw the letter {'L', 'O', 'G'} positioned such that it's
lower-left corner is where the turtle currently is at.
Return the turtle to this location after drawing the letter.
I can and should document this via comments. Since all of my new commands that draw letters work the same way - they are symmetric - a couple of comment lines before all of the definitions will suffice.
;the following commands (drawG, drawL, and drawO) draw a
;letter (the last char of their names). The letters are
;centered in a box that is 100 turtle steps tall and
;50 turtle steps wide. The lower-left corner of the box
;is where the turtle is. The turtle is returned to this
;location after the letter is drawn.
This becomes the contract for using the drawL, drawO, and drawG commands. I can now use these commands as black boxes. And, since they are all symmetric they support the same contract, I can now write a command that moves the turtle right one letter position.
|
The program to draw the word "LOGO" becomes a list of the new commands I've written.
|
So, I've replaced pseudocode with user-defined commands that I wrote. Each was simple to do by itself. The final program is composed of these new commands and is simple and easy to read itself.
Here is the full text of my program to draw the word "LOGO"
Practice:
Complete Your Own Word Program
Using my example as a model, write your own drawXxxx program (where XXXX is your word. You should define a new command for each letter in your word. Include a moveRightLetter command definition. Your program should then simply be a list of these user-defined commands.
Logo Animation - Procedures in Action
Figure 7.4
Practice: Rewrite DrawHouse
At the end of the previous lesson you were asked to write a program that drew a simple house. Figure 4.8 shows the house you were to draw. You did this by first writing out the process as pseudocode and then translated this to Logo. Rewrite your drawHouse program using our new approach of defining commands for parts of the house. Write new commands named:
- drawFront,
- drawRoof,
- drawDoor, and
- drawWindow.
Use them in your program, substituting them for the primitive commands that did the drawing they now do.
Figure 4.8
Investigation
Bring up Wikipedia in a browser and search for the words "procedure call" and read about the history of procedures, their creation and calling (invoking) them.
Go to the Table of Contents
On to Iteration