..:: A guide for You who wanna be a programming master!! ::..

Menu
Procedures and Functions
Tips 'n Tricks

---------------------
Home
---------------------
History
---------------------
Program Structure
---------------------
Compilers
---------------------


Materials :
  1. Basics
  2. Input-output
  3. Expressions
  4. Procedures and Functions


Procedures

A procedure is a subprogram. Subprograms help reduce the amount of redundancy in a program. Statements that are executed over and over again but not contained in a loop are often put into subprograms.

Subprograms also facilitate top-down design. Top-down design is the tackling of a program from the most general to the most specific. For example, top down design for going from one room to another starts out as:

  • Get out of first room
  • Go to second room
  • Go into second room

Then it is refined to

  • Get out of first room
    • Go to door
    • Open the door
    • Get out of door
    • Close door
  • ...

Just going to the door can be refined further:

  • Get out of first room
    • Go to door
      • Get out of seat
      • Turn towards door
      • Walk until you almost bump into it

This, of course, can be further refined to say how much exercise should be given to your cardiac myofibrils, and how much adenosine diphosphate should be converted to adenosine triphosphate by fermentation or aerobic respiration. This may seem to be too detailed, but for computer programming, this is, in effect what you have to do. The computer can't understand general statements -- you must be specific.

Main tasks should be contained in procedures, so in the main program, you don't have to worry about the details. This also makes for reusable code. You can just keep your procedures in one file and link that into your program.

A procedure has the same basic format as a program:

procedure Name;

const
  (* Constants *)

var
  (* Variables *)

begin
  (* Statements *)
end;

There is a semicolon (not a period) at the end.

To call the procedure from the main program, just use the name, like you would writeln.

     Name;

Procedures are very often used to output data. It's that simple (until the next lesson, of course).

back to top

Parameters

A parameter list can be included as part of the procedure heading. The parameter list allows variable values to be transferred from the main program to the procedure. The new procedure heading is:

procedure Name (formal_parameter_list);

The parameter list consists of several parameter groups, separated by semicolons:

param_group_1; param_group2; ... ; param_groupn

Each parameter group has the form:

identifier_1, identifier_2, ... , identifier_n : data_type

The procedure is called by passing arguments (called the actual parameter list) of the same number and type as the formal parameter list.

procedure Name (a, b : integer; c, d : real);
begin
  a := 10;
  b := 2;
  writeln (a, b, c, d)
end;

Suppose you called the above procedure from the main program as follows:

alpha := 30;
Name (alpha, 3, 4, 5);

When you return to the main program, what is the value of alpha? 30. Yet, alpha was passed to a, which was assigned a value of 10. What actually happened was that a and alpha are totally distinct. The value in the main program was not affected by what happened in the procedure.

This is called call-by-value. This passes the value of a variable to a procedure.

Another way of passing parameters is call-by-reference. This creates a link between the formal parameter and the actual parameter. When the formal parameter is modified in the procedure, the actual parameter is likewise modified. Call-by-reference is activated by preceding the parameter group with a VAR:

VAR identifier1, identifier2, ..., identifiern : datatype;

In this case, constants and literals are not allowed to be used as actual parameters because they might be changed in the procedure.

Here's an example which mixes call-by-value and call-by-reference:

procedure Name (a, b : integer; VAR c, d : integer);
begin
  c := 3;
  a := 5
end;

begin
  alpha := 1;
  gamma := 50;
  delta := 30;
  Name (alpha, 2, gamma, delta);
end.

Immediately after the procedure has been run, gamma has the value 3 because c was a reference parameter, but alpha still is 1 because a was a value parameter.

This is a bit confusing. Think of call-by-value as copying a variable, then giving the copy to the procedure. The procedure works on the copy and discards it when it is done. The original variable is unchanged.

Call-by-reference is giving the actual variable to the procedure. The procedure works directly on the variable and returns it to the main program.

In other words, call-by-value is one-way data transfer: main program to procedure. Call-by-reference goes both ways.

back to top

Functions

Functions work the same way as procedures, but they always return a single value to the main program through its own name:

function Name (parameter_list) : return_type;

Functions are called in the main program by using them in expressions:

a := Name (5) + 3;

Be careful not to use the name of the function on the right side of any equation inside the function. That is:

function Name : integer;
begin
  Name := 2;
  Name := Name + 1
end.

is a no-no. Instead of returning the value 3, as might be expected, this sets up an infinite recursive loop. Name will call Name, which will call Name, which will call Name, etc.

The return value is set by assigning a value to the function identifier.

Name := 5;

It is generally bad programming form to make use of VAR parameters in functions -- functions should return only one value. You certainly don't want the sin function to change your pi radians to 0 radians because they're equivalent -- you just want the answer 0.

back to top

Scope

Scope refers to where certain variables are visible. You have procedures inside procedures, variables inside procedures, and your job is to try to figure out when each variable can be seen by the procedure.

A global variable is a variable defined in the main program. Any subprogram can see it, use it, and modify it. All subprograms can call themselves, and can call all other subprograms defined before it.

The main point here is: within any block of code (procedure, function, whatever), the only identifiers that are visible are those defined before that block and either in or outside of that block.

program Stupid;
var A;

  procedure StupidToo;
  var A;
  begin
    A := 10;
    writeln (A)
  end;

begin (* Main *)
  A := 20;
  writeln (A);
  StupidToo;
  writerln (A);
end. (* Main *)

The output of the above program is:

20
10
20

The reason is: if two variable with the same identifiers are declared in a subprogram and the main program, the main program sees its own, and the subprogram sees its own (not the main's). The most local definition is used when one identifier is defined twice in different places.

Here's a scope chart which basically amounts to an indented copy of the program with just the variables and minus the logic:

[Image of scope chart]

  • Everybody can see global variables A, B, and C.
  • However, in procedure Alpha the global definition of A is replaced by the local definition.
  • Beta1 and Beta2 can see variables VCR, Betamax, and cassette.
  • Beta1 cannot see variable FailureToo, and Beta2 cannot see Failure.
  • No subprogram except Alpha can access F and G.
  • Procedure Beta can call Alpha and Beta.
  • Function Beta2 can call any subprogram, including itself (the main program is not a subprogram).

back to top

Recursion

Recursion is a difficult topic to grasp. However, it's very easy to apply once you understand it. The programming assignment for this chapter will involve recursion.

Recursion means allowing a function or procedure to call itself. It keeps calling itself until some limit is reached.

The summation function, designated by an uppercase Sigma in mathematics, is a popular example of recursion:

function Summation (num : integer) : integer;
begin
  if num = 1 then
    Summation := 1
  else
    Summation := Summation(num-1) + num
end;

Suppose you call Summation for 3.

a := Summation(3);

  • Summation(3) becomes Summation(2) + 3.
  • Summation(2) becomes Summation(1) + 2.
  • At 1, the recursion stops and becomes 1.
  • Summation(2) becomes 1 + 2 = 3.
  • Summation(3) becomes 3 + 3 = 6.
  • a becomes 6.

Recursion works backward until a given point is reached at which an answer is defined, and then works forward with that definition, solving the other definitions which rely upon that one.

All recursive procedures/functions should have some sort of test so stop the recursion. Under one condition, called the base condition, the recursion should stop. Under all other conditions, the recursion should go deeper. In the example above, the base condition was if num = 1. If you don't build in a base condition, the recursion will either not take place at all, or become infinite.

back to top

Forward Referencing

After all these confusing topics, here's something easy.

Remember that procedures/functions can only see variables and other subprograms that have already been defined? Well, there is an exception.

If you have two subprograms, each of which calls the other, you have a dilemma that no matter which you put first, the other still can't be called from the first.

To resolve this chicken-and-the-egg problem, use forward referencing.

procedure Later (parameter list); forward;

procedure Sooner (parameter list);
begin
  ...
  Later (parameter list);
end;
...
procedure Later;
begin
  ...
  Sooner (parameter list);
end;

The same goes for functions. Just stick a forward; at the end of the heading.

You can compile your work by pressing "F9" when in the IDE. Or if you wanna launch it directly after compiling, just press "Ctrl+F9"!!

..:: by_Zain Fathoni ::..
.: SMA N 1 Jember / XII.Rintisan :.
copyright © 2008
Adapted from www.tayoue.com