Procedures and Functions

Procedures

As loops allow us to reuse code blocks, procedures are another mechanism of easing our coding efforts while upholding the integrity of our program’s design. A loop allows us to reuse code immediately – to repeat a task over and over. A procedure on the other hand can be called at any time. The block of code in the procedure can be executed at any time by calling the procedure. Since the code in this block may be used at any point in the program it is not generally part of the program itself, but instead defined as a separate small program on its own.

As a contained block of program code a procedure has many parts similar to a general program. It has input in the form of zero or more parameters variables, it may return output (see functions below), and it has a block of program code – the procedure-body – that may contain its own variables, program-code, and even procedure calls. In addition a procedure has a unique name through which it can be called, that is have its procedure-body executed on the input provided.

When designing and defining a procedure for use in our program we begin with a procedure prototype. A prototype serves as a blueprint for the procedure we wish to define. It consists of the procedure name, the input conditions (aka preconditions), and the output conditions (aka postconditions).

Prototype

The naming conventions of a procedures face similar constraints as naming variables. Names that are informative and concise are the best. The name of a procedure should reflect its purpose and possibly inform the use how that purpose is carried out. Concise names are favored because they are easier to remember and use in practice.  Names like proc, procedure, and function are poor names as they don’t carry a lot of meaning about the procedure. If a procedure initializes your program then call it init. If it helps you load a database then call it loadDatabase. As with variable names the best choices are ones that help us understand the procedures purpose while being short and easy to remember.

The input-conditions of a procedure state the number, names, and type of all input variables to the procedures as well as any restrictions or assumptions made about the input. Some procedures have no input variables, but may still have assumptions made prior to running. Other procedures will have a finite list of input variables, each with a type and possible range of value it might assume. An input variable is called a parameter or an argument. Input variables are variables so they can have a type, which is usually stated upon definition of the procedure. Their names must also be unique from other variables but in most languages the procedure is considered a separate scope. A scope determines how much of the program your variable can be read or written to. A procedure’s input variables have a scope restricted only to that procedure. This means these variables can only be read or written to from within the procedure-body. The parameters have no meaning before the procedure is called and they must be assigned a value when the procedure begins.

Variables defined within the procedure also have a scope restricted to the procedure. Again this means that outside of the procedure-body we cannot access these variables – the have no meaning. These procedure variables are called local variables since they are local to the procedure. Further, variables defined outside of the procedure are outside the procedure’s scope and cannot be accessed from within the procedure. So if you need the procedure to have access to some variables defined outside the procedure consider making these variables input-variables. Otherwise your only other choice to make the variables global in scope meaning they can be accessed from anywhere. The drawback of global variables is the same as its strength. The variables can be accessed from anywhere in the program which gives you the programmer an amazing freedom when using them, but it also means you might accidentally change the variable when you do no mean to. Restricting the scope of variables helps to keep these bugs out of our code and is generally considered good programming style.

The output-conditions of a procedure state the type of output variable (if it exists) as well as any conditions assumed to hold after the processing of the procedure. A procedure with an output variable is called a function. Many procedures only carry out data manipulation and have no output variable. In this case the output-conditions state what can be assumed to have occurred to the input variables or other program variables after the procedure is executed.

Consider the challenge of using the Turtle Graphics to make a procedure to draw a square of different sizes. We need an input-variable determining the size of the square, or more precisely the length of one of the square’s sides. There is no output variable for this procedure, but we do have an assumption after the procedure. Specifically we assume that a square of the appropriate size has been drawn. We might state the prototype of our example procedure as follows.
square
   input: length - a positive number
   output: none - a square with sides of size length is drawn
The purpose of the prototype is to help guide the definition of the procedure itself but also to help characterize the use of the procedure for others. If a procedure is going to be useful to other programmers after it is written they need to know exactly how the procedure works. They want to know what effects it might have on their variables if they use it in their program (they don’t want to cause unexpected errors). Often the prototype is the only part of the procedure the other programmers will ever see and so it is important both to have a precise prototype and to make sure that the prototype is correct and complete for the procedure. A procedure prototype is sometimes called an interface or an API (application programming interface) when it is used to instruct others how to use the procedure.

Procedure Code

In some languages the procedure is defined and declared at the same time with no explicit prototype. In this cases the prototype is given as a comment or in a help file for those that wish to use the procedure. This example declaration given in no particular language has explicitly stated the procedure name, the names of the procedure’s input parameters (conventionally placed in brackets), and the procedure-body (the indented code).
square(length)
   repeat 4 times
      right 90
      forward length
end square
This declaration is part of our program, but it will not be executed unless it is called in the main body of the program. The important part of the procedure is the procedure-body and it must be defined before the procedure can be used. The scope of the procedure is indicated by the square and end square tags surrounding the procedure-body. These scope identifiers may have special characters assigned to them like { and }.

Square Square

Calling a Procedure

Once you have a procedure defined and declared you may use it in your program as you like. You can call the procedure by using the procedure’s name, and assigning values to the procedure’s input variables. Generally this is done merely by stating the procedure’s name followed by the parameters contained in brackets as depicted in this example.
square(10)
This procedure call to the procedure square will assign the value 10 to the variable length then execute the procedure-body. In this case it will draw a square with sides of length 10.  Calling the procedure with a different value will cause a different size square to be drawn.  If the procedure has more than one parameter then it is important to list the values in the same order as the procedure definition.  The program cannot know which order we wish to assign the values to parameters so it assumes we are providing the values in the same order as the definition.  If we have an improper number of parameters in our call (not matching our definition) then we will get an error.  Likewise if we assign a value of the wrong type to an input variable.

We could call the square procedure more than once with different values for length.

square(10)
square(100)
These two calls would draw two squares, one on top of another, but with one of size 10 and the other of size 100. The square procedure can now be called as needed to draw a square whenever we need a square. The power of procedures is that we can now use the square procedure, perhaps along with other procedures, to build more complicated procedures. Procedures allow us to reuse and build upon the programs we have already solved.

Functions

A function is a procedure that return a value, that is, it has an output.  These procedures might compute a mathematical function, or lookup a name in a table, or otherwise find a solution to a problem for us and provide us with that solution.  Typically a procedure that returns no value is meant to do something whereas a function that returns a value is meant to calculate something.

Functions help us calculate the values we need in our program.  We could create a function that computes Pythagoras’ theorem to calculate the lengths of the hypotenuse in right angle triangles we draw.  Here is a prototype for such a function.

hypotenuse
   input - a positive number side1, a positive number side2
   output - a number equal to the square root of side1^2 + side2^2
This function returns a number as is common in math related functions. Another math related function might compute the roots of a quadratic function using the quadratic formula. Such calculations are common tasks for functions. Other tasks might be to retrieve a piece of data from a collection. Perhaps we want to find the salesman that sold the most for us this year to award a bonus. Perhaps we need to find the median student in a class of students. These tasks require computation to complete, but it is the outcome – the output – we are interested in with functions as opposed to procedures.

Right Angle Triangle Right Angle Triangle

Circle Circle

Modularization

There are a few rules computer scientists live by. The first rule is: Reuse – don’t write code you don’t have to. We’ve seen this already in the idea of a loop. A loop reuses the code in the loop-body to save us some typing. A procedure also satisfies this rule. Writing one procedure to draw squares of any size allows us to reuse that code for any square we might want to draw. A second rule is: Divide and conquer – write a program one piece at a time. Never try to write the entire program from beginning to end. Break it into bits – modules – that have a logical connection. If some of the bits are the same then following rule one, assign a procedure and reuse the code. Modularization is the design principle that says before writing a large-ish program it is a good idea to break it into its logical components on the drawing board. Plan for the procedures you might need and see where you can take advantage of good design and code reuse to safe yourself coding time and lines of code. A good rule of modularization is: One procedure per module; one module per procedure. This guideline helps us to remember where is best to cut the program up. Sometimes the logical divisions can be hard to see. First we have one procedure per module. This means when you have identified a logical task or module assign only one procedure to it. Do not break up units beyond need and do not replicate modules in similar functions. Second we have one module per procedure. Do not try to fit more than one task into a procedure. Good design will have to breaking that procedure up in time so it is best to design for it. One way to test if you have selected a logical task for the procedure comes when you must select a name for your procedure. If you can’t say concisely what the procedure will do, then perhaps you have too many tasks or only a part of a task. Reconsider your design and you might find it easier to find a name.

Challenges

Below are some procedure prototypes and images corresponding to more challenging problems for the turtle graphics programs. Use the freestyle demo to try your best at solving them. Try to solve them all or quit after you feel comfortable with the programming.

Freestyle Freestyle

Freestyle Polygon

Leave a comment

You must be logged in to post a comment.