Procedures & Functions Grade 11

User-defined procedures and functions let you break code into reusable, named blocks. This makes programs easier to read, maintain and debug.

T2Term 2 · Procedures, Functions & Parameters

What Is a Method?

A method is a named block of code that performs a specific task. Instead of writing the same instructions over and over inside your event handlers, you write them once, give that block a name, and then simply call that name whenever you need the task done. In Delphi we build methods in two forms: procedures and functions.

ANALOGY

Think of a method like a recipe card in a cookbook. The recipe is written down once. Whenever you want that dish, you don't rewrite the steps from scratch — you just fetch the card and follow it. A method works exactly the same way: write the steps once, then "fetch" them by name as often as you like.

Why Do We Break Code Into Methods?

When you are starting out it can feel like extra work to split your program into little named blocks. But experienced programmers do it for very good reasons:

Important Rule

Each method should do only one job. If a method is trying to do several things at once, that is usually a sign it should be split into smaller methods.

What Is a Procedure?

A procedure is a named block of code that does a task but does not send a value back to where it was called. It simply carries out its instructions — showing a message, clearing some boxes, drawing on a canvas — and then control returns to the program.

ANALOGY

A procedure is like asking someone to "switch off the lights". They go and do the job. You don't expect them to hand you anything back — you just expect the task to be done.

Procedures

Without Parameters

Delphi — declare and call
// Declaration (above the event handlers)
procedure ShowHello;
begin
  ShowMessage('Hello!');
end;

// Calling it
procedure TForm1.btnShowClick(Sender: TObject);
begin
  ShowHello;   // called alone
end;

With Parameters

Delphi
procedure DisplayGreeting(sMessage, sName: string);
begin
  ShowMessage(sMessage + ' ' + sName);
end;

// Call with arguments
DisplayGreeting('Good morning', 'Ms Coetzee');

Parameters vs Arguments

A parameter is a placeholder name listed in the method's declaration — it stands for a value the method will receive. An argument is the actual value you pass in when you call the method. In short: parameters live in the declaration; arguments are the real values you supply at the call.

ANALOGY

Think of a parameter as a labelled jar called "sName" sitting empty on the shelf when the recipe is written. The argument is the actual "Ms Coetzee" you scoop into that jar when you finally cook. The jar's label is the parameter; what you put in it is the argument.

Example: in DisplayGreeting(sMessage, sName: string) the names sMessage and sName are parameters. When you call DisplayGreeting('Good morning', 'Ms Coetzee'), the strings 'Good morning' and 'Ms Coetzee' are the arguments.

Value Parameters

A value parameter means the method receives a copy of the argument. The method can change that copy freely inside itself, but the original variable back in the calling code stays untouched. This is the default and safest kind of parameter, because the caller never has to worry about its variables being changed unexpectedly.

ANALOGY

A value parameter is like giving someone a photocopy of a document. They can scribble all over their copy, but your original is safe at home.

Reference (VAR) Parameters

A reference parameter — Delphi calls it a VAR parameter, marked with the keyword var in the declaration — doesn't hand the method a copy of anything. It points the method straight at the caller's own variable, so any change made inside the method sticks after the method finishes and control returns to the caller.

ANALOGY

A reference parameter is like handing someone your original document instead of a photocopy. Whatever they write on it is now permanently on your original — there's no separate copy shielding it.

Delphi — declaring a VAR parameter
procedure DoubleIt(var iNum: Integer);
begin
  iNum := iNum * 2;   // changes the CALLER's variable directly
end;

// Call — no assignment needed, iScore itself is changed
DoubleIt(iScore);

Several of Delphi's own built-in procedures rely on VAR parameters to hand back a result without being functions — Inc and Dec are everyday examples:

StatementEquivalent to
Inc(iScore, iBonus);iScore := iScore + iBonus;
Dec(iScore, iPenalty);iScore := iScore - iPenalty;

Here iScore is the VAR parameter — it's the one actually overwritten with a new total — while iBonus (or iPenalty) is only ever a value parameter that Delphi reads once and then discards.

Value or VAR — how to choose

Reach for a plain value parameter whenever a method only needs to look at the data. Switch to a VAR parameter the moment a method has to alter the caller's variable itself — a procedure that swaps two values around, or one that tops up a running total that lives outside the method, are both classic cases.

Returning More Than One Value

A function is limited to handing back a single value through Result. When a task genuinely needs to report back two or more separate pieces of information at once, write a procedure with more than one VAR parameter instead — each VAR parameter becomes its own "answer slot" that the procedure fills in, and every one of them is available to the caller as soon as the procedure finishes.

Delphi — one procedure, two VAR parameters
procedure CheckAttendance(iDaysPresent, iTotalDays: Integer; var bMeetsRule: Boolean; var sNote: string);
begin
  bMeetsRule := (iDaysPresent / iTotalDays) >= 0.8;
  if bMeetsRule then
    sNote := 'Meets the 80% attendance requirement.'
  else
    sNote := 'Below the 80% attendance requirement.';
end;

// Call — both bOk and sMsg are filled in by this one call
CheckAttendance(iPresent, iTotal, bOk, sMsg);
lblStatus.Caption := sMsg;

iDaysPresent and iTotalDays stay ordinary value parameters, since the procedure only needs to read them. bMeetsRule and sNote are VAR parameters, so after the call bOk holds whatever was assigned to bMeetsRule, and sMsg holds whatever was assigned to sNote — two results from one procedure call.

What Is a Function?

A function is a named block of code that does a task and then returns exactly one value back to where it was called. Inside the function you store the answer in the special variable Result, and that answer is handed back so you can use it — store it, display it, or calculate further with it.

ANALOGY

A function is like asking someone "How much is the bread?" They go, check, and come back with an answer you can use. A function always brings something back; a procedure does not have to.

Functions

Without Parameters

Delphi
function GetAnswer: Integer;
begin
  Result := 42;
end;

// Must be assigned
iVal := GetAnswer;
A second way to set the return value

Besides assigning to Result, Delphi also lets you assign the return value straight to the function's own name — so GetAnswer := 42; works exactly the same as Result := 42; above. You'll come across both styles in Delphi code; Result is the more modern and readable habit, so it's the one used throughout this page.

With Parameters

FUNCTION HEADER ANATOMY Keyword Function name — used to call it function AddNumbers (num1, num2: Integer) : Parameter list — names & data types Integer ; Return type — the data type sent back to the caller

In one line: function AddNumbers(num1, num2: Integer): Integer;

Delphi
function AddNumbers(num1, num2: Integer): Integer;
begin
  Result := num1 + num2;
end;

// Call
iAnswer := AddNumbers(5, 3);          // = 8
lblResult.Caption := IntToStr(AddNumbers(iA, iB));

Function Example — Calculate Average

Delphi
function CalcAverage(iTotal, iCount: Integer): Real;
begin
  if iCount = 0 then
    Result := 0
  else
    Result := iTotal / iCount;
end;

// Use it
rAvg := CalcAverage(iSum, iNumStudents);
lblAvg.Caption := FloatToStr(rAvg);

Procedures vs Functions

ProcedureFunction
Returns a value?No (or modifies var parameters)Yes — always returns exactly one value
Called how?Alone as a statementAs part of another statement (assigned)
Keywordprocedurefunction

Local vs Global Variables

Where you declare a variable decides which parts of your program are allowed to see it. This is called the variable's scope.

ANALOGY

A local variable is like a note you scribble on a scrap of paper during one phone call — useful while you're on the call, but you throw it away the moment you hang up, and nobody in the next room ever sees it. A global variable is like a whiteboard on the office wall — anyone in any room can walk up, read it, or write on it, and what's written stays there until someone deliberately changes it.

Delphi — local declaration (inside a method)
procedure TForm1.btnClick(Sender: TObject);
var
  sName   : string;    // local — only exists inside this procedure
  iNumber : Integer;
begin
  ...
end;
Delphi — global declaration (unit level, above all procedures)
type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1   : TForm1;
  sName   : string;    // global — every procedure in this unit can see and change it
  iNumber : Integer;
Prefer local variables and parameters

It is tempting to make everything global so you never have to worry about passing values around — but this makes bugs much harder to find, because any method could be the one that changed the value. Rather keep variables local and use parameters to pass values into a method and Result (or a var parameter) to pass values back out. Save global variables for values that genuinely need to be shared everywhere, such as settings used across the whole form.

Declaring a Method as Part of the Form's Class

Every procedure and function example so far has been a stand-alone routine, sitting in the unit above the event handlers. Delphi offers a second way to write your own methods: you can make a procedure or function part of the Form's own class, exactly like an event handler already is. To do this, add its declaration inside the Form's class(TForm) ... end; block — normally in the private section — and then write its full code down in the implementation section using the same TForm1.MethodName pattern you already recognise from event handlers.

Let Delphi build the skeleton for you

Once a method is declared in the private section, click anywhere inside its name and press Ctrl+Shift+C. Delphi will generate an empty procedure TForm1.MethodName; begin ... end; skeleton in the implementation section for you to complete — the same shortcut you may already use to generate event handlers.

Delphi — a method declared as part of TForm1
type
  TForm1 = class(TForm)
    btnCalc: TButton;
    procedure btnCalcClick(Sender: TObject);
  private
    { Private declarations }
    procedure ShowAverage(iTotal, iCount: Integer);   // declaration
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

// definition — the class name TForm1 goes in front of the method name
procedure TForm1.ShowAverage(iTotal, iCount: Integer);
begin
  lblAverage.Caption := FloatToStr(iTotal / iCount);
end;

Both styles are valid Delphi and do exactly the same job. A stand-alone procedure is quick for a small helper needed in only one place; making a method part of the Form's class is the tidier choice once several event handlers need to share it, because every part of the Form's behaviour — its event handlers and its helper methods alike — is then declared together inside one class.

Passing an Array as a Parameter

An array can be passed into a procedure or function just like any other value — but Delphi won't let you type the array's size directly into a parameter list (writing something like arrScores: array[1..5] of Integer as a parameter is not allowed). Instead, declare the array as a named type above the Form's class first, and then use that type name wherever you need it — in the parameter list, and in any var block that needs a matching array.

Delphi — declaring an array type so it can be used as a parameter
type
  TQuizScores = array[1..5] of Integer;   // declared above the Form's class

  TForm1 = class(TForm)
    ...
  private
    function CalcTotal(arrScores: TQuizScores): Integer;
  public
    ...
  end;

implementation

function TForm1.CalcTotal(arrScores: TQuizScores): Integer;
var
  i, iSum: Integer;
begin
  iSum := 0;
  for i := 1 to 5 do
    iSum := iSum + arrScores[i];
  Result := iSum;
end;

Any variable declared with TQuizScores — for example arrQuiz1: TQuizScores; inside an event handler's own var block — can now be passed as the argument, because the variable and the parameter are built from the exact same named type.

Worked Example — Validate & Grade a Mark

A real button click usually calls several methods together. Here two functions (each returning a value) and one procedure (which just does a job) work as a team: one function checks the input is valid, another turns a mark into a symbol, and the procedure prints a line.

Delphi — two functions and a procedure
// FUNCTION — returns True/False (used to make a decision)
function IsValidMark(iMark: Integer): Boolean;
begin
  Result := (iMark >= 0) and (iMark <= 100);
end;

// FUNCTION — returns a string (used inside an expression)
function GetSymbol(iMark: Integer): string;
begin
  if iMark >= 80 then Result := 'A'
  else if iMark >= 70 then Result := 'B'
  else if iMark >= 60 then Result := 'C'
  else if iMark >= 50 then Result := 'D'
  else if iMark >= 40 then Result := 'E'
  else if iMark >= 30 then Result := 'F'
  else Result := 'G';
end;

// PROCEDURE — does a job, returns nothing
procedure TForm1.AddLine(sText: string);
begin
  memOut.Lines.Add(sText);
end;

// BUTTON — ties them together
procedure TForm1.btnProcessClick(Sender: TObject);
var
  iMark: Integer;
begin
  iMark := StrToInt(edtMark.Text);
  if IsValidMark(iMark) then              // function used AS the condition
    AddLine(IntToStr(iMark) + ' = symbol ' + GetSymbol(iMark))  // function inside an expression, then procedure prints
  else
    ShowMessage('Enter a mark between 0 and 100.');
end;
Function or procedure — how to choose

Notice that IsValidMark and GetSymbol hand a value back that you use (in the if and inside the message), while AddLine just does the job of printing. That is the whole rule: if you need an answer back, write a function; if you only need something done, write a procedure.

Why Use Procedures and Functions?

To bring it all together, here are the practical benefits you gain every time you reach for a method instead of writing one long block of code: