1. Computing

Understanding and Using Functions and Procedures

for Delphi beginners ...

By

Have you ever found yourself writing the same code over and over to perform some common task within event handlers? Yes! It's time for you to learn about programs within a program. Let's call those mini programs subroutines.

Intro to subroutines

Subroutines are an important part of any programming language, and Delphi is no exception. In Delphi, there are generally two types of subroutines: a function and a procedure. The usual difference between a function and a procedure is that a function can return a value, and a procedure generally will not do so. A function is normally called as a part of an expression.

Take a look at the following examples:

 procedure SayHello(const sWhat:string) ;
 begin
   ShowMessage('Hello ' + sWhat) ;
 end;
 
 function YearsOld(const BirthYear:integer): integer;
 var
   Year, Month, Day : Word;
 begin
   DecodeDate(Date, Year, Month, Day) ;
   Result := Year - BirthYear;
 end; 
Once subroutines have been defined, we can call them one or more times:
 procedure TForm1.Button1Click(Sender: TObject) ;
 begin
   SayHello('Delphi User') ;
 end;
 
 procedure TForm1.Button2Click(Sender: TObject) ;
 begin
   SayHello('Zarko Gajic') ;
   ShowMessage('You are ' + IntToStr(YearsOld(1973)) + ' years old!') ;
 end; 

Functions and Procedures

As we can see, both functions and procedures act like mini programs. In particular, they can have their own type, constants and variable declarations inside them.

Take a closer look at a (miscellaneous) SomeCalc function:

 function SomeCalc
    (const sStr: string;
     const iYear, iMonth: integer;
     var iDay:integer): boolean;
 begin
 ...
 end; 
Every procedure or function begins with a header that identifies the procedure or function and lists the parameters the routine uses, if any. The parameters are listed within parentheses. Each parameter has an identifying name and usually has a type. A semicolon separates parameters in a parameter list from one another.

sStr, iYear and iMonth are called constant parameters. Constant parameters cannot be changed by the function (or procedure). The iDay is passed as a var parameter, and we can make changes to it, inside the subroutine.

Functions, since they return values, must have a return type declared at the end of the header. The return value of a function is given by the (final) assignment to its name. Since every function implicitly has a local variable Result of the same type as the functions return value, assigning to Result has the same effect as assigning to the name of the function.

Positioning and Calling Subroutines

Subroutines are always placed inside the implementation section of the unit. Such subroutines can be called (used) by any event handler or subroutine in the same unit that is defined after it.

Note: the uses clause of a unit tells you which units it can call. If we want a specific subroutine in a Unit1 to be usable by the event handlers or subroutines in another unit (say Unit2), we have to:

  • Add Unit1 to the uses clause of Unit2
  • Place a copy of the header of the subroutine in the interface section of the Unit1.
This means that subroutines whose headers are given in the interface section are global in scope.

When we call a function (or a procedure) inside its own unit, we use its name with whatever parameters are needed. On other hand, if we call a global subroutine (defined in some other unit, e.g. MyUnit) we use the name of the unit followed by a period.

 ...
 //SayHello procedure is defined inside this unit
 SayHello('Delphi User') ;
 //YearsOld function is defined inside MyUnit unit
 Dummy := MyUnit.YearsOld(1973) ;
 ... 
Note: functions or procedures can have their own subroutines embedded inside them. An embedded subroutine is local to the container subroutine and cannot be used by other parts of the program. Something like:
 procedure TForm1.Button1Click(Sender: TObject) ;
   function IsSmall(const sStr:string):boolean;
   begin
    //IsSmall returns True if sStr is in lowercase, False otherwise
    Result:=LowerCase(sStr)=sStr;
   end;
 begin
   //IsSmall can only be uses inside Button1 OnClick event
   if IsSmall(Edit1.Text) then
    ShowMessage('All small caps in Edit1.Text')
   else
    ShowMessage('Not all small caps in Edit1.Text') ;
 end; 

Related resources:

©2014 About.com. All rights reserved.