
==== Step 5:
Step Title     : Procedures and Functions
File Name      : MP_5.txt
Author Note    : How modular are you?
Example Source : none
Author         : Michael Preslar / E_Maus
Date           : October 5th, 1998
Length         : 15 pages
Layout         : - Intro to Procedures
                 - Intro to Scope
                 - Advanced Procedures
                 - Scope Part 2
                 - Functions
                 - Retrospect
====
Please refer back to "intro.txt" for complete documentation of copyrights,
and author information.

Step 4 Foreword
---------------
As mentioned in step 0, Pascal is a modular language. What makes it modular?
If youre like most other self-taught programmers (yes, you are a programmer!)
youve already looked at source codes from other packages. If the package
was of a good size, Im sure you saw the words procedure, function, and uses
quite a few times. The proper use of those words is what makes the language
modular.

Modular itself means it can be "chopped up". In this and the following few
lessons, ill teach you ways in which you can chop your own code up. Why would
you want to do that? If youre using the same piece of code over and over
again, itd be a good idea to put it in a procedure or something. Still
dont understand? Dont worry.. Just read along with the lesson, and youll
learn everything pretty easily.

  ========================== Intro to Procedures ===========================
Take a look at this example. It introduces quite a few new things. However,
once explained, its easy to follow.

program LoginThingy;

var name:string;
    ch:char;

procedure get_a_name;
begin
 repeat
  write('What name do you want to use: ');
  readln(name);
  write('Are you sure? ');
  readln(ch);
  ch:=upcase(ch);
 until ch='Y';
end;

begin
 writeln; writeln;
 writeln('Michael''s Procedure showing example..');
 get_a_name;
 writeln('The name you picked is: ',name);
 write('I hope this is right.. is it? ');
 readln(ch);
 ch:=upcase(ch);
 if ch='N' then
  begin
   get_a_name;
   writeln('Your name is now: ',name);
  end;
end.

and there it is. You have two different blocks of code there. the procedure
block and the main block. Lets take a look at a few things..

1) When declaring a procedure, you say "procedure" and then whatever you want
   the procedure to be named. In this example, the procedure is named,
   "get_a_name"..
2) Every procedure has its own begin and end pair.
3) Although I didnt in this example, you can declare variables, constants,
   and other types in a procedure. Just do it after the procedure heading,
   and before the procedure's begin.
4) Once a procedure has been successfully declared, it can be used as many
   times as youd like. In the above example program, youll notice I used the
   "get_a_name" procedure 2 times.
5) The code for the procedure is known as a "procedural block". This block
   of code follows the same rules that the main block would follow. With the
   exception of the procedure's last "end". Its _always_ followed by a
   semi-colon.

  =========================== Intro to Scope ===============================
Lets look at something in the above example program "loginthingy".. Notice
that I declared the variables "name" and "ch" before I declared the procedure.
Since I did that, the procedure can use those variables. However, had declared
the variables after the procedural block, but before the main block, only
the main block could have used them. This is known as "scope".

When declaring a procedure, any variables, constants, types, other procedures
and everything else above it is in the scope of that procedure. However, if
you declare a variable, constant, type or whatever else in the procedure, then
the scope of those will only be that procedure. Confused? Wait for the next
example. Itll show what Im talking about..

  =========================== Advanced Procedures ==========================
This will be a tough section. Id advise reading over this section until you
understand it. Im also assuming you understand the "intro to procedures"
section..

{----<snip>----}

program LoginThingy2;

var name:string;
    ch:char;

procedure get_a_name;

  procedure namething(var thename:string);
  var b:byte;
  begin
   if length(thename) < 2 then exit;
   thename[1]:=upcase(thename[1]);
   for b:= 2 to length(thename) do
    if thename[b-1]=' ' then thename[b]:=upcase(thename[b]);
  end;

begin
 name:='';
 repeat
  write('What name do you want to use: ');
  readln(name);
  namething(name);
  write(name,' Are you sure? ');
  readln(ch);
  ch:=upcase(ch);
 until ch='Y';
end;

procedure funny(mf:boolean);
begin
if mf=false then
  writeln('Mr. ',name,'? That doesnt sound right. Ms. ',name,' is much better.')
else
  writeln('Ms. ',name,'? That doesnt sound right. Mr. ',name,' is much better.')
end;

var MaleOrFemale:boolean;

begin
 writeln; writeln;
 writeln('Michael''s second Procedure showing example..');
 get_a_name;
 writeln('The name you picked is: ',name);
 write('I hope this is right.. is it? ');
 readln(ch);
 ch:=upcase(ch);
 if ch='N' then
  begin
   get_a_name;
   writeln('Your name is now: ',name);
  end;
 write('Are you male or female? [m/f] ');
 readln(ch);
 ch:=upcase(ch);
 if ch='M' then maleorfemale:=false else maleorfemale:=true;
 funny(maleorfemale);
end.

{----<snip>----}

Wow.. 56 lines long. But I must say.. This has to be our first full program.
Yes, I know. This program accomplishes nothing. Wait a minute.. Yes it does.
It has some great examples of the syntax of some advanced procedures. Lets
look at that syntax, shall we?

This program consists of 3 procedures: "get_a_name", "namething", and "funny".

First, lets check out "namething".  "Namething" basically takes a string that
is supposed to be a name, and capitalizes the right letters. There are much
better ways to do this, so I wouldnt use the one listed here. "Namething" is
declared within "get_a_name", so only "get_a_name" can use it. There are three
other things to notice about "namething". First, the variable "b". ONLY the
"namething" procedure can use it. Second.. the word "exit". "exit" allows you
to break out of whatever block youre in and return to the calling block. You
can even use "exit" in loops! When you do, the program will just exit out of
the loop.

The third thing to notice is rather important. Look at the header for
"namething"... procedure namething(var thename:string); The important part
is the "var thename:string".. just save that for now. Ill go back and cover
it in a second, when the time is right.

The next procedure to check out is "get_a_name". Yes, its the exact same thing
as "get_a_name" from the first example, except for one difference. The
"namething" procedure is declared here, and then used within.

The last procedure is "funny". Okay, so "funny" isnt so funny. But it shows
something for me. And now, the time is right to discuss the important "thing"
from the procedure "namething". "So what is it, already?!?" you ask. Lets
take a look at the headers of "funny" and "namething":

procedure funny(mf:boolean);
procedure namething(var thename:string);

Both allow you to pass a variable to it. That is legal. As a matter of fact,
you can pass any type to a procedure, and as many as memory allows. When you
go to use these procedures, you have to pass a variable to it of the same type
in the same order. And in the procedure, when you want to use the passed
type, you use the one in the procedure's heading, not the one being passed
to it. Notice in "funny", i used the "mf" variable, and not "maleorfemale".

Something Im sure youve noticed, and are wondering about.. The way mf was
declared, and the way thename was declared. Whats the difference? A variable
declared with a "var" in front of it (var thename:string) keeps all changes
made to it within the procedure. A variable without the "var" (mf:boolean)
will keep the same value it had before the procedure.

So now youre wondering how to declare multiple variables to pass to a
procedure.. Easy answer.. Take a look at this:

procedure pretend_this_is_a_procedure(this:string; that:boolean;
          var i:integer; whatalongname:char);

What to look at:
1) Procedure names can be as long as you want. But no spaces in the name.
2) Youre only allowed 64k of memory. So you can declare as many different
   types as you want, as long as you dont use more than 64k in that program
   block. In other words.. You use memory for each type declared in a
   procedure's heading, plus the memory for the "working type" that will be
   used to call the procedure.
3) When declaring multiple types, you have to put a semi-colon in between
   each one.
4) When you go to use this procedure.. The variables you pass it have to be
   of the same type, and in the same order that you declared it. This might
   would be a way to use it:
     pretend_this_is_a_procedure('hello!',true,count,ch);
   suppose count was declared as an integer, and ch as a char. Notice the
   comma's between each type.

  ============================= Scope part 2 ===============================
Looking back over the discussion in "advanced procedures", I noticed how scope
really became an issue. How?

1) the variables "name" and "ch" which were declared before anything else
   has the scope of the _entire_ program.
2) the procedure "namething" was declared within "get_a_name", so it only has
   the scope of "get_a_name".
3) No types were declared in "get_a_name" or in it's heading, but.. Had one
   been declared in its heading, or before "namething", they would have the
   scope of "get_a_name" and "namething". But had one been declared after
   "namething" was declared, then only "get_a_name" couldve used it.
4) Although "get_a_name" wasnt used in "funny", it could have been. Since
   "get_a_name" was declared before "funny", it had the scope of "funny" and
   the main block of code. However, "funny" only had the scope of the main
   block.
5) MaleOrFemale was declared after "funny", but before the main block, so
   the only thing that could use it is the main block.

  =============================== Functions ================================
Okay. So weve covered a lot of ground about procedures.. So whats a function?
Easy. Functions are easy enough, actually, that youll only be learning one
new thing. Check out the example:

program functionthingy;

function tf(ff:boolean):string;
begin
if ff=true then tf:='TRUE' else
  tf:='FALSE';
end;

var ch:char;
    go:boolean;
begin
write('Continue? ');
readln(ch);
ch:=upase(ch);
if ch='Y' then go:=true else go:false;
writeln(tf(go));
end.

A function follows the same rules as a procedure. However, you can declare
and use the function's name just like a type. In this example, we can make
reference to "tf" as a string variable. Yes, you can pass many types to a
function just like a procedure.

  ============================== Retrospect ================================
Whew! Wow, was that a mouthful.. For your information, it took me close to 6
hours (off and on) to type this up. Hope it helps. We covered procedures,
functions, and the all important scope.

An upcoming lesson on Units and Include files will have more about scope.