Ex 01
Ex 01
note There is another very specific syntactical difference between Object Pascal and other languages,
that is presence of a semicolon at the end of the function or procedure signature in the definition,
before the begin keyword.
There are two ways to indicate the result of the function call, assign the value to
function name or use the Result keyword:
// classic style
function DoubleOld (Value: Integer) : Integer;
begin
DoubleOld := Value * 2;
end;
// modern alternative
note Differently from the classic Pascal language syntax, Object Pascal has actually three ways to indi-
cate the result of a function, including the Exit mechanism discussed in this chapter in the section
“Exit with a Result”.
The use of Result instead of the function name to assign the return value of a func-
tion is the most common syntax and tends to make the code more readable. The use
of the function name is a classic Pascal notation, now rarely used.
Again, by comparison the same function could be written with the C language syntax
as the following:
int Double (int Value)
{
return Value * 2;
};
If this is how these routines can be defined, the calling syntax is relatively straight-
forward, as you type in the identifier followed by the parameters within parenthesis.
In cases where there are no parameters, the empty parenthesis can be omitted
(again, unlike languages based on the C syntax). This code snippet and several fol-
lowing ones are part of the FunctionsTest project of this chapter:
// call the procedure
Hello;
Forward Declarations
When you need to use an identifier (of any kind), the compiler must have already
seen it, to know to what the identifier refers. For this reason, you usually provide a
full definition before using any routine. However, there are cases in which this is not
possible. If procedure A calls procedure B, and procedure B calls procedure A, when
you start writing the code, you will need to call a routine for which the compiler still
hasn't seen a definition.
In this cases (and in many others) you can declare the existence of a procedure or
function with a certain name and given parameters, without providing its actual
code. One way to declare a procedure or functions without defining it is to write its
name and parameters (referred to as the function signature) followed by the forward
keyword:
procedure NewHello; forward;
Later on, the code should provide a full definition of the procedure (which must be
in the same unit), but the procedure can now be called before it is fully defined. Here
is an example, just to give you the idea:
procedure DoubleHello; forward;
procedure NewHello;
begin
if MessageDlg ('Do you want a double message?',
TMsgDlgType.mtConfirmation,
[TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo],
0) = mrYes then
DoubleHello
else
ShowMessage ('Hello');
end;
procedure DoubleHello;
begin
NewHello;
NewHello;
end;
note The MessageDlg function called in the previous snippet is a relatively simple way to ask a confir-
mation of the user in the FireMonkey framework (a similar functions exists in the VCL framework
as well). The parameters are the message, the type of dialog box, and buttons you want to display.
The result is the identifier of the button that was selected.
This approach (which is also part of the FunctionTest application project) allows
you to write mutual recursion: DoubleHello calls Hello, but Hello might call Dou-
bleHello too. In other words, if you keep selecting the Yes button the program will
continue showing the message, and show each twice for every Yes. In recursive code,
there must be a condition to terminate the recursion, to avoid a condition known as
stack overflow.
note Function calls use a stack for the parameters, the return value, local variables and more. If a func-
tions keeps calling itself in an endless loop, the memory area for the stack (which is generally of a
fixed and predefined size, determined by the linker) will terminate through an error known as a
stack overflow. Needless to say that the popular developers support site (www.stackoverflow.-
com) took its name from this programming error.
A Recursive Function
Given I mentioned recursion and gave a rather peculiar example of it (with two pro-
cedures calling each other), let me also show you a classic example of a recursive
function calling itself. Using recursion is often an alternative way to code a loop.
To stick with a classic demo, suppose you want to compute the power of a number,
and you lack the proper function (which is available in the run-time library, of
course). You might remember from math, that 2 at the power of 3 corresponds to
multiplying 2 by itself 3 times, that is 2*2*2.
One way to express this in code would be to write a for loop that is executed 3 times
(or the value of the exponent) and multiplies 2 (or the value of the base) by the cur-
rent total, starting with 1:
function PowerL (Base, Exp: Integer): Integer;
var
I: Integer;
begin
Result := 1;
for I := 1 to Exp do
Result := Result * Base;
end;
An alternative approach is to repeatedly multiply the base by the power of the same
number, with a decreasing exponent, until the exponent is 0, in which case the result
is invariably 1. This can be expressed by calling the same function over and over, in a
recursive way:
function PowerR (Base, Exp: Integer): Integer;
var
I: Integer;
begin
if Exp = 0 then
Result := 1
else
Result := Base * PowerR (Base, Exp - 1);
end;
The recursive version of the program is likely not faster than the version based on
the for loop, nor more readable. However there are scenarios such as parsing code
structures (a tree structure for example) in which there isn't a fixed number of ele-
ments to process, and hence writing a loop is close to impossible, while a recursive
functions adapts itself to the role.
In general, though, recursive code is powerful but tends to be more complex. After
many years in which recursion was almost forgotten, compared to the early days of
programming, new functional languages such Haskell, Erlang and Elixir make heavy
use of recursion and are driving this idea back to popularity.
In any case, you can find the two power functions in the code in the FunctionTest
application project.
note The two power functions of the demo don't handle the use of a negative exponent. The recursive
version in such a case will loop forever (an until the program hits a physical constraint). Also, by
using integers it is relatively fast to reach the maximum data type size and overflow it. I wrote
these functions with these inherent limitations to try to keep their code simple.
What Is a Method?
We have seen how you can write a forward declaration in the interface section of a
unit of by using the forward keyword. The declaration of a method inside a class
type is also considered a forward declaration.
But what exactly is a method? A method is a special kind of function or procedure
that is related to one of two data types, a record or a class. In Object Pascal, every
time we handle an event for a visual component, we need to define a method, gener-
ally a procedure, but the term method is used to indicate both functions and
procedures tied to a class or record.
Here is an empty method automatically added to the source code of a form (which is
indeed a class, as we'll explore much later in the book):