CHAPTER 5 - The Pascal procedures and functions In order to properly define procedures and functions we need to lay some groundwork in the form of a few definitions. These are important concepts, so pay close attention. Program Heading - This is the easiest part since it is only one line, at least it has been in all of our programs up to this point. It is simply the "program" line, and it never needs to be any more involved than it has been up to this point in TURBO Pascal. Declaration Part - This is the part of the Pascal source code in which all constants, variables, and user defined auxiliary operations are defined. In some of the programs we have examined, there have been one or more var declarations. These are the only components of the declaration part we have used to this point. There are actually five components in the declaration part, and the procedures and functions are the fifth part. We will cover the others in the next chapter. Statement Part - This is the last part of any Pascal program, and it is what we have been calling the main program. It is one compound statement bracketed with the reserved words "begin" and "end". It is very important that you grasp the above definitions because we will be referring to them constantly during this chapter, and throughout the remainder of this tutorial. With that introduction, lets go on to our first Pascal program with a procedure in it, in fact, it will have three procedures. THE FIRST PROCEDURES Load PROCED1 as your first example file with a procedure and display it on your monitor. You will notice that it doesn't look like anything you have seen up to this point because it has procedures in it. Lets go back to our definitions from above. The first line is the Program Heading which should pose no difficulty. The Declaration Part begins with the var statement in line 4 and continues down through and including all three procedures ending in line 19. Lines 21 through 26 constitute the Statement Part. It may seem strange that what appears to be executable Pascal statements, and indeed they are executable statements, are contained in the Declaration Part rather than the Statement Part. This is because of the Pascal Page 26 CHAPTER 5 - The Pascal procedures and functions definition and it will make sense when we have completed our study of procedures and functions. Continuing to examine PROCED1, we will make note of the program itself, which is the Statement Part. The program, due to the nature of Pascal and the carefully chosen procedure names, clearly tells us what it will do. It will write a header, eight messages, and an ending. The only problem we are faced with is, how will it write these messages? This is where the Declaration Part is called upon to define these operations in detail. The Declaration Part contains the three procedures which will completely define what is to be done by the procedure calls in the main program. It should be clear to you that the definitions of the procedures should be in the Definition Part of the program because that is exactly what they do. In the case of a var, a variable is defined for later use by the main program, and in the case of a procedure, the procedure itself is defined for later use by the main program. Lets arbitrarily pick one of the procedures, the first, and examine it in detail. The first executable statement we come to in the main program is line 22 and says simply, Write_A_Header, followed by the usual end of statement, the semicolon. This is a simple procedure call. When the compiler finds this statement it goes looking for a predefined procedure of that name which it can execute. If it finds one in the Declaration Part of the program, it will execute that procedure. If it doesn't find a user defined procedure, it will search the Pascal library for a system defined procedure and execute it. The Write and Writeln statements are system procedures, and you have already been using them quite a bit, so procedures are not completely new to you. If it doesn't find the procedure defined in either place, it will generate an error message. HOW TO CALL A PROCEDURE To call a procedure, we simply need to state its name. To define a simple procedure, we use the reserved word "procedure" followed by its calling name, with a semicolon as a terminator. Following the Procedure Heading, there is the Declaration Part of the procedure followed by a body which is nothing more than a compound statement bracketed by the reserved words "begin" and "end". This is identical to the Statement Part of the main program except that the procedure ends with a semicolon instead of a period. Any valid Pascal statements can be put between the begin and Page 27 CHAPTER 5 - The Pascal procedures and functions end, and in fact, there is no difference in what can be put in a procedure and what can be put in the main program. The program we are examining would be no different if we would eliminate the first procedure completely and move the Writeln contained in it down to the Statement Part in place of Write_A_Header. If that is not clear, go back and reread the last two paragraphs until it is. Lines 23 and 24 will cause the procedure named Write_A_Message to be called 8 times, each time writing a line of output. Suffice it to say at this time that the value of the variable Count, as defined here, is available globally, meaning anywhere in the entire Pascal program. We will define the scope of variables shortly. Finally, the last procedure call is made, causing the ending message to be displayed, and the program execution is complete. Having examined your first Pascal procedures, there is a fine point that is obvious but could be easily overlooked. We mentioned the unbroken rule of Pascal in an earlier chapter and it must be followed here too. "Nothing can be used in Pascal until it has been defined". The procedures must all be defined ahead of any calls to them, once again emphasizing the fact that they are part of the Declaration Part of the program, not the Statement Part. Compile and run PROCED1 to verify that it does what you expect it to do. MORE PROCEDURE CALLS Assuming you have run PROCED1 successfully and understand its output, lets go on to PROCED2 and examine it. In this program we will see how to call a procedure and take along some data for use within the procedure. To begin with, notice that there are three procedure calls in the Statement Part of the program and each has an additional term not contained in the calls in the last program, namely the variable name Index within brackets. This is Pascals way of taking a variable parameter to the procedure when it is called. You will notice that the variable Index is defined as an integer variable in the very top of the Declaration Part. Since we are taking an integer type variable along when we visit the procedure Print_Data_Out, it had better be expecting an integer variable as input or we will have a type mismatch. In fact, observing the procedure heading itself in line 7, indicates that it is indeed expecting an integer variable but it prefers to call the variable Puppy Page 28 CHAPTER 5 - The Pascal procedures and functions inside of the procedure. Calling it something different poses no problem as long as the main program doesn't try to call its variable Puppy, and the procedure doesn't try to use the name Index. Both are actually referring to the same piece of data but they simply wish to refer to it by different names. Observe that the next procedure is called with Index as a parameter and the procedure prefers to call it by the name Cat. In both cases, the procedures simply print out the parameter passed to it, and each then try to modify the value passed to it before passing it back. We will see that one will be successful and the other will not. We are in a loop in which Count is incremented from 1 to 3 and Pascal does not allow us to modify the loop variable so we make a copy of the value in line 21 and call it Index. We can then modify Index in the main program if we desire. CALL BY VALUE In line 7, the procedure heading does not contain a var in front of the passed parameter and therefore the parameter passing is only one way because of the way Pascal is defined. Without the reserved word var in front of the variable Puppy, the system makes a copy of Index, and passes the copy to the procedure which can do anything with it, using its new name, Puppy, but when control returns to the main program, the original value of Index is still there. The copy of Index named Puppy is modified in the procedure, but the original variable Index remains unchanged. So you can think of the passed parameter without the var as one way parameter passing. This is a "call by value" because only the value of the variable is passed to the procedure. CALL BY REFERENCE In line 13, the second procedure has the reserved word "var" in front of its desired name for the variable, namely Cat, so it can not only receive the variable, it can modify it, and return the modified value to the main program. A copy is not made, but the original variable named Index is actually passed to this procedure and the procedure can modify it, therefore communicating with the main program. The name Catin the procedure is actually another name for the variable named Index in the main program. A passed parameter with a var in front of it is therefore a two way situation. This is a "call by reference" since the reference to the original variable is passed to the procedure. Page 29 CHAPTER 5 - The Pascal procedures and functions SOME NEW TERMINOLOGY The parameter name in the calling program is referred to as the actual parameter, and the parameter name in the procedure is referred to as the formal parameter. In the last example then, the actual parameter is named Index and the formal parameter in the procedure is named Cat. It should be pointed out that it is called a formal parameter whether it is a "call by reference" or a "call by value". This terminology is used in many other programming languages, not only in Pascal. When you run this program, you will find that the first procedure is unable to return the value of 12 back to the main program, but the second procedure does in fact succeed in returning its value of 35 to the main program. Spend as much time as you like studying this program until you fully understand it. It should be noted that as many parameters as desired can be passed to and from a procedure by simply making a list separated by commas in the calls, and separated by semicolons in the procedure. This will be illustrated in the next example program. Compile and run PROCED2 and study the output. You should be able to comprehend all of the output. If it is not clear, reread the last few paragraphs. For your own enlightenment, examine PROCED3 for an example of a procedure call with more than one variable in the call. Normally, you would group the three input values together to make the program more readable, but for purposes of illustration, they are separated. Observe that the variable Fruit is a two way variable because it is the 3rd variable in the actual parameter list and corresponds to the 3rd formal parameter in the procedure header. Compile and run PROCED3 to see that it does what you expect it to do based on the above explanation. "CALL BY REFERENCE" OR "CALL BY VALUE"? It may seem to you that it would be a good idea to simply put the word var in front of every formal parameter in every procedure header to gain maximum flexibility, but using all "call by references" could actually limit your flexibility. There are two reasons to use "call by value" variables when you can. First is simply to shield some data from being corrupted by the procedure. This is becoming a very important topic is Software Engineering known as "information hiding" and is the primary basis behind Object Page 30 CHAPTER 5 - The Pascal procedures and functions Oriented Programming which is far beyond the scope of this tutorial. Secondly is the ability to use a constant in the procedure call. Modify line 17 of PROCED3 as follows; Add_The_Fruit(12,Orange,Fruit,Pear); and compile and run the program. Since Value1 is a "call by value", the constant 12 can be used and the program will compile and run. However, if you change line 17 to; Add_The_Fruit(Apple,Orange,32,Pear); you will find that it will not compile because Total is a "call by reference" and the system must be able to return a value for the formal parameter Total. It cannot do this because 32 is a constant, not a variable. The prior discussion should indicate to you that both "call by value" and "call by reference" have a useful place in Pascal programming and it is up to you to decide which you should use. When you are satisfied with the present illustration, we will go on to study the scope of variables using PROCED4. A MULTIPLY DEFINED VARIABLE If you will examine PROCED4, you will notice that the variable Count is defined twice, once in the main program var block and once in the var block contained within the procedure named Print_Some_Data. This is perfectly legal and is within the Pascal definition. The variable Index is defined only in the main program var block and is valid anywhere within the entire Pascal program, including the procedures. The variable Count is also defined in the main program var block and is valid anywhere within the entire Pascal program, except within the procedure where another variable is defined with the same name Count. The two variables with the same name are in fact, two completely different variables, one being available only outside of the procedure and the other being available only within the procedure. The variable More_Stuff is defined within the procedure, so it is invisible to the main program, since it is defined at a lower level than that of the main program. Any variable is available at any point in the program following its definition but only at the level of definition Page 31 CHAPTER 5 - The Pascal procedures and functions or below. This means that any procedure in the Declaration Part of a program can use any variable defined in the Declaration Part of the program provided that the definition occurs prior to the procedure. Any variable defined in a procedure cannot be used by the main program since the definition is at a lower level than the main program. Be sure to compile and run PROCED4 before continuing on to the next example program. PROCEDURES CALLING OTHER PROCEDURES Load and examine PROCED5 to see an example of procedures that call other procedures. Keep in mind that, "Nothing can be used in Pascal until it has been previously defined", and the order of procedures will be clear in this example. Note that procedure Three calls procedure Two which in turn calls procedure One. Compile and run PROCED5 and study the output until you understand why it outputs each line in the order that it does. Now that you have a good working knowledge of procedures, we need to make another important point. Remember that any Pascal program is made up of three parts, the Program Heading, the Declaration Part, and the Statement Part. The Declaration Part is composed of five unique components, four of which we will discuss in detail in the next chapter, and the last component, which is composed of some number of procedures and functions. We will cover functions in the next example, so for now simply accept the fact that it is like a procedure. A procedure is also composed of three parts, a Procedure Heading, a Declaration Part, and a Statement Part. A procedure, by definition, is therefore nothing more or less than another complete Pascal program embedded within the main program, and any number of procedures can be located in the Declaration Part of the main program. These procedures are all in a line, one right after another. Since a procedure is defined like the main program, it would seem to be possible to embed another procedure within the Declaration Part of any procedure. This is perfectly valid and is often done, but remember that the embedded procedure can only be called by the procedure in which it is embedded, not by the main program. This is a form of information hiding which is becoming popular in modern software engineering. Page 32 CHAPTER 5 - The Pascal procedures and functions The previous paragraph is probably a bit difficult to grasp. Don't worry about it too much now, as you become proficient as a Pascal programmer, you will very clearly see how that is used. NOW LET'S LOOK AT A FUNCTION Now to keep a promise, lets examine the program named FUNCTION to see what a function is and how to use it. In this very simple program, we have a function that simply multiplies the sum of two variables by 4 and returns the result. The major difference between a function and a procedure is that the function returns a single value and is called from within a mathematical expression, a Writeln command, or anywhere that it is valid to use a variable, since it is really a variable itself. Observing the Function Heading of the function, in line 6, reveals the two input variables inside the parenthesis pair being defined as integer variables, and following the parenthesis is a colon and another "integer". The last "integer" is used to define the type of the variable being returned to the main program. Any call to this function is actually replaced by an integer upon completion of the call. Therefore in line 14, the function is evaluated and the value returned is used in place of the function call. The result of the function is assigned to the variable Feet. Note that a function always returns a value and it may return additional values if some of its parameters are defined as "call by reference". Be sure to compile and run this program. NOW FOR THE MYSTERY OF RECURSION One of the great mysteries of Pascal to many people, is the recursion of procedure calls. Simply defined, recursion is the ability of a procedure to call itself. Examine the Pascal example file RECURSON for an example of recursion. The main program is very simple, it sets the variable Count to the value 7 and calls the procedure Print_And_Decrement. The procedure prefers to refer to the variable by the name Index but that poses no problem for us because we understand that the name of the formal parameter can be any legal identifier. The procedure writes a line to the video display with the value of Index written within the line, and decrements the variable. The if statement introduces the interesting part of this program. If the variable is greater than zero, and it is now 6, then the procedure Print_And_Decrement is called Page 33 CHAPTER 5 - The Pascal procedures and functions once again. This might seem to create a problem except for the fact that this is perfectly legal in Pascal. Upon entering the procedure the second time, the value of Index is printed as 6, and it is once again decremented. Since it is now 5, the same procedure will be called again, and it will continue until the value of Index is reduced to zero when each procedure call will be completed one at a time and control will return to the main program. ABOUT RECURSIVE PROCEDURES This is really a stupid way to implement this particular program, but it is the simplest recursive program that can be written and therefore the easiest to understand. You will have occasional use for recursive procedures, so don't be afraid to try them. Remember that the recursive procedure must have some variable converging to something, or you will have an infinite loop. Compile and run this program and observe the value decrementing as the recursion takes place. THE FORWARD REFERENCE Occasionally you will have a need to refer to a procedure before you can define it. In that case you will need a forward reference. The program FORWARD has an example of a forward reference in it. In this program, each one of the procedures calls the other, a form of recursion. This program, like the last, is a very stupid way to count from 7 to 0, but it is the simplest program possible with the forward reference. The first procedure, Write_A_Line, has its header defined in exactly the same manner as any other procedure but instead of the normal procedure body, only the reserved word "forward" is given. This tells the compiler that the procedure will be defined later. The next procedure is defined as usual, then the body of Write_A_Line is given with only the reserved word "procedure" and the procedure name. The variable reference has been defined earlier. In this way, each of the procedure names are defined before they are called. It would be possible, by using the forward reference in great numbers, to move the main program ahead of all procedure definitions and have the program structured like some other languages. This style of programming would be perfectly legal as far as the compiler is concerned, but the resulting program would be very nonstandard and confusing. You would do well to stick with conventional Pascal Page 34 CHAPTER 5 - The Pascal procedures and functions formatting techniques and use the forward reference sparingly. Be sure you compile and run this program. PROGRAMMING EXERCISES 1. Write a program to write your name, address, and phone number with each Writeln in a different procedure. 2. Add a statement to the procedure in RECURSON to display the value of "Index" after the call to itself so you can see the value increasing as the recurring calls are returned to the next higher level. 3. Rewrite TEMPCONV putting the centigrade to fahrenheit formulas in a function call. Page 35